Purview-API-PowerShell.ps1


<#PSScriptInfo
 
.VERSION 1.10
 
.GUID 5fd81e92-c46d-45ea-b591-86524bf24498
 
.AUTHOR abandyop (arindamba@microsoft.com)
 
.COMPANYNAME Microsoft
 
.COPYRIGHT Microsoft Open Source
 
.TAGS
 
.LICENSEURI https://opensource.org/licenses/MIT
 
.PROJECTURI https://github.com/Azure/Azure-Purview-API-PowerShell
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES Release Version 1.x
Sample Usage Batch Mode : PS >> Purview-API-PowerShell -APIDirect -HTTPMethod GET -PurviewAPIDirectURL "https://{your_purview_account_name}.purview.azure.com/catalog/api/atlas/v2/types/typedefs?api-version=2021-07-01"
Sample Usage Interactive/GUI Mode : PS >> Purview-API-PowerShell -PurviewAccountName YOUR_PURVIEW_ACCOUNT_NAME
 
.PRIVATEDATA
 
.DESCRIPTION
 
*******************************************************
** Execute Azure Purview RESTful APIs via PowerShell **
*******************************************************
- Full Documentation, Usage, Samples & Example Commands : https://github.com/Azure/Azure-Purview-API-PowerShell
- Run Interactive Mode: >> Purview-API-PowerShell -PurviewAccountName YOUR_PURVIEW_ACCOUNT_NAME
#>
 

### Purview API via PowerShell ###
## Arindam Bandyopadhyay MSFT (arindamba@microsoft.com) ##

param (
    [Parameter(Mandatory=$false)]
    [string]$TenantId,
    [Parameter(Mandatory=$false)]
    [string]$SubscriptionId,
    [Parameter(Mandatory=$false)]
    [string]$PurviewAccountName,
    [Parameter(Mandatory=$false)]
    [switch]$APIDirect,
    [Parameter(Mandatory=$false)]
    [string]$PurviewAPIDirectURL,
    [Parameter(Mandatory=$false)]
    [string]$HTTPMethod,
    [Parameter(Mandatory=$false)]
    [string]$InputFile,
    [Parameter(Mandatory=$false)]
    [string]$OutputFile
)
############ Functions -------------------------------------------------------------------------------

function ReplaceRESTParametersInURI (
    [string] $URI
) {
    $APIRefCSVParamsFirstColumn = $APIRefCSVParams | select -Unique -ExpandProperty API_PARAMETER
    foreach ($MatchParam IN $APIRefCSVParamsFirstColumn) {
        if ($URI -match $MatchParam) {
            if ($MatchParam -eq "{subscriptionId}") {
                $ParamValue = $SubscriptionId
            } elseif ($MatchParam -eq "{accountName}") {
                $ParamValue = $PurviewAccountName
            } else {
                $ParamValue = $(Write-Host "$MatchParam=" -ForegroundColor DarkCyan -NoNewLine; Read-Host)
            }
            $URI = $URI -replace $MatchParam,$ParamValue
        }
    }
    if ($URI -match "\{.*\}") {

    }
    if ($URI -contains "?" ) {
        $URI = $URI + "&"
    } else {
        $URI = $URI + "?&"
    }
    RETURN $URI
}

############ Most Important Function - Running API -------------------------------------------------------------------------------

function RunAPI (
    [string] $Method,
    [string] $PVAPIDirectURL
) {
    $ErrorMsg = "`r`n `
        --- Purview API URL & Endpoint NOT VALID. `r`n `
        --- Purview API Endpoint begins with https://{your_purview_account_name}.purview.azure.com/ or https://management.azure.com/. Please supply correct API URL and try again. `r`n`
        --- Note: Purview APIs end with mandatory &api-version={version} parameter, where {version} = 2021-07-01 or 2019-11-01-preview or some other older version. `r`n `
        --- Refer `"https://docs.microsoft.com/en-us/rest/api/purview/`" for detailed documentation and usage on fully qualified Purview API URLs."

    IF ($PVAPIDirectURL -ne $null -AND $PVAPIDirectURL.StartsWith("https://")) {} else {
        Write-Host $ErrorMsg -ForegroundColor DarkYellow
        RETURN
    } 
    IF ($PVAPIDirectURL -Match ".purview.azure.com/"  -OR  $PVAPIDirectURL -Match "management.azure.com/" -OR $PVAPIDirectURL -contains "api-version=") {} else {
        Write-Host $ErrorMsg -ForegroundColor DarkYellow
        RETURN
    }
    IF ($PVAPIDirectURL -Match "api-version=") {} else {
        Write-Host $ErrorMsg -ForegroundColor DarkYellow
        RETURN
    }
    IF ($HTTPMethod -NotIn ("GET", "PUT", "POST", "DELETE", "CREATE", "PATCH", "TRACE", "HEAD", "CONNECT")) {
        Write-Host "--- HTTP Method NOT Provided Or Incorrect. It should be one out of [GET PUT POST DELETE PATCH TRACE HEAD CONNECT]. Please Try Again." -ForegroundColor DarkCyan
        RETURN
    }
    IF ($HTTPMethod -in ("PUT","POST")){
        Write-Host "--- HTTP Body (Payload) : Sending File (purview-api-body-payload.json) as HTTP API Body..." -ForegroundColor DarkYellow 
    Try {
        IF ($InputFile) {} else {
            Write-Host "--- InputFile Parameter Missing. Sending Empty Body." -ForegroundColor DarkYellow
        }
        $HTTPBody = Get-Content $InputFile -ErrorAction Stop
    } Catch {
        Write-Host "--- InputFile Parameter (Containing Request Body JSON) Is Required For This API. File NOT Found or INVALID. Sending Empty Body." -ForegroundColor DarkYellow
        $HTTPBody = @{}
    }}

    $Headers = @{}
    $Headers.Add("Accept","*/*")
    $Headers.Add("User-Agent","Windows PowerShell 7.x Purview API PS")
    $Headers.Add("Authorization","Bearer $($AccessTokenData.Token)")
    $Headers.Add("Content-Type","application/json")
    $timer = [System.Diagnostics.Stopwatch]::StartNew()
    Write-Host "Invoking API : Sending Request ... " -ForegroundColor DarkCyan -NoNewLine
    Write-Host " $HTTPMethod $PVAPIDirectURL"

    Try {
        $PurviewAPIResponse = Invoke-RestMethod -Method $HTTPMethod -Uri $PVAPIDirectURL -Headers $Headers -Body $HTTPBody
    } Catch {
        Write-Host $_ :-> $_.Exception
    }

    $timer.Stop()
    Write-Host "API Response Received :-> " -ForegroundColor Green
    $PurviewAPIOutFile = $PurviewAPIResponse | ConvertTo-JSON -Depth 100
    Write-Output $PurviewAPIOutFile
    Write-Host "API Latency / Time Elapsed :-> " -ForegroundColor Green
    Write-Output $timer.Elapsed
    $PurviewAPIResponse = ""
    $DateString = Get-Date -Format yyyy_MM_dd_hh_mm_ss_fffffff
    IF ($OutputFile) {} else {$OutputFile="purview-api-output-$DateString.json"}
    $PurviewAPIOutFile | Set-Content -Path $OutputFile
}


############ Fetch Access Token & If Fails, Re-Login To Azure & Get Access Token ---------------------------------------------------------------------------------------------------------------------------
if ($APIDirect) {
    if ($PurviewAPIDirectURL) {} else {
        Write-Host "--- PurviewAPIDirectURL parameter cannot be BLANK in APIDirect Mode. Please supply the fully qualified Azure Purview API URL and try again !." `
        " Refer `"https://docs.microsoft.com/en-us/rest/api/purview/`" for detailed documentation and usage on fully qualified Purview API URLs." -ForegroundColor DarkCyan
        Exit 2
    }
}
DO {
TRY {
    $AccessTokenDataMgmt = (Get-AzAccessToken -ResourceUrl "https://management.azure.com")
    $AccessTokenData = (Get-AzAccessToken -ResourceUrl "https://purview.azure.net")
    Write-Output $AccessTokenData
}
CATCH {
if ($TenantId -and $SubscriptionId) {
    Set-AzContext -Tenant $TenantId -Subscription $SubscriptionId
}
elseif ($TenantId) {
    Set-AzContext -Tenant $TenantId
}
elseif ($SubscriptionId) {
    Set-AzContext -Subscription $SubscriptionId
}
$TenantId = (Get-AzContext).Tenant.Id
$SubscriptionId = (Get-AzContext).Subscription.Id
if (-Not($TenantId) -OR -Not($SubscriptionId)) {
    Connect-AzAccount
    $TenantId = (Get-AzContext).Tenant.Id
    $SubscriptionId = (Get-AzContext).Subscription.Id
}
Save-AzProfile -Path .\MyAzureProfile.JSON -Force
}
} WHILE ("$AccessTokenData" -eq $null -OR ("$AccessTokenData").trim() -eq "")

############ Checking Run Mode, If Direct API Mode, Exit After This Section ------------------------------------------------------------------

if ($APIDirect) {
    RunAPI $HTTPMethod $PurviewAPIDirectURL
    Exit 0
}
elseif ($PurviewAccountName) {} else {
    $PurviewAccountName = Read-Host "Please Enter Your Purview Account/Catalog Name"
}

############ Download CSV From Repo ------------------------------------------------------------------

Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Azure/Azure-Purview-API-PowerShell/main/Purview_API_Reference.csv" -OutFile "Purview_API_Reference.csv"
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Azure/Azure-Purview-API-PowerShell/main/Purview_API_Reference_Parameters.csv" -OutFile "Purview_API_Reference_Parameters.csv"
$APIRefCSV = Import-Csv -Path Purview_API_Reference.csv
$APIRefCSVParams = Import-Csv -Path Purview_API_Reference_Parameters.csv

############ Repeat Section Below To Run APIs --------------------------------------------------------------------------------------------------------------------------------------------------------------------

DO {
DO {
    $Mode = $(Write-Host "Enter : [G] GUI - Interactive Assistance On Help, Usage & Syntax of Purview APIs [T] Text Mode - Enter API Command(s) Manually [Q] Quit :: " -ForegroundColor Cyan -NoNewLine; Read-Host)
} WHILE ($Mode -notin ("q","Q","g","G","t","T"))
if ($Mode.SubString(0,1) -in ("q","Q")) {  Exit 1 }
if ($Mode.SubString(0,1) -in ("g","G")) { $Mode = "G" } else { $Mode = "T" }

if ($Mode -eq "G") {
    $SelectedAPI = $APIRefCSV   | Out-GridView -Title "Execute Purview API" -OutputMode Single
    $APICategory = $SelectedAPI | Select-Object -ExpandProperty Category
    $APICommand  = $SelectedAPI | Select-Object -ExpandProperty Command
}
else {
    $ValidAPICategories = $APIRefCSV | select -Unique -ExpandProperty Category
    DO {
        $APICategory = $(Write-Host "Enter API Category : Valid Values ( $ValidAPICategories ) : " -ForegroundColor Yellow -NoNewLine; Read-Host)
    } WHILE ($APICategory -notin $ValidAPICategories)
    
    $ValidAPICommands   = $APIRefCSV | Where-Object {$_.Category -eq $APICategory} | select -ExpandProperty Command
    DO {
        $APICommand  = $(Write-Host "Enter API Command : Valid Values ( $ValidAPICommands ) : " -ForegroundColor DarkYellow -NoNewLine; Read-Host)
    } WHILE ($APICommand -notin $ValidAPICommands)

}

$APISelectedRow = $APIRefCSV | Where-Object {$_.Category -eq $APICategory -and $_.Command -eq $APICommand}
$APIDomain  = $APISelectedRow | select -ExpandProperty APIURIDomain; if ($APICategory -ne "management") { $APIDomain  = $PurviewAccountName + $APIDomain }
IF ($APIDomain -contains "management.azure") {$AccessTokenData = $AccessTokenDataMgmt}

$APIURIPath = $APISelectedRow | select -ExpandProperty APIURIPath
$HTTPMethod = $APISelectedRow | select -ExpandProperty Method
$APIVersion = $APISelectedRow | select -ExpandProperty APIVersion
$PurviewAPIEndpointURL = ReplaceRESTParametersInURI ($URI="https://"+$APIDomain+$APIURIPath)
$PurviewAPIEndpointURL = $PurviewAPIEndpointURL + $APIVersion

Write-Host "Domain : " -NoNewLine
Write-Host $APIDomain -ForegroundColor DarkGreen 
Write-Host "Ready To Execute ::::::: API Request :-> $HTTPMethod " -NoNewLine
Write-Host $PurviewAPIEndpointURL -ForegroundColor DarkGreen 

RunAPI $HTTPMethod $PurviewAPIEndpointURL
}
WHILE (1)

############## END --------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Rudimentary way of fetching Access Token
#$PostBody = @{grant_type='client_credentials'; client_id='servicePrincipalId'; client_secret='servicePrincipalKey'; resource="https://purview.azure.net"} | ConvertTo-Json
#$AccessTokenData = Invoke-WebRequest -UseBasicParsing https://login.windows.net/$TenantId/oauth2/token -ContentType "application/json" -Method POST -Body $PostBody
#
# Future Support for Service Principal
# If -ServicePricipal = TRUE, which is when user wants to login via Service Principal, user must Enter "ApplicationID" for the username and "ServicePrincipalSecret" as the password.
# Otherwise script will prompt for service principal credentials and stores them for the session. Enter your application ID for the username and service principal secret as the password when prompted.
# The ServicePrincipal switch parameter indicates that the account authenticates as a service principal.