DimeScheduler.InstallExchangeApp.ps1
<#PSScriptInfo
.VERSION 0.0.1.0 .GUID 4812b98b-f5e4-48e4-8dfd-05a0d347178b .AUTHOR Hendrik Bulens .COMPANYNAME Dime Software .ICONURI https://cdn.dimescheduler.com/dime-scheduler/v2/shape.png #> <# .SYNOPSIS Creates a Microsoft Entra ID App Registration for the Dime.Scheduler Exchange connector. .DESCRIPTION Creates a Microsoft Entra ID App Registration for the Dime.Scheduler Exchange connector. .PARAMETER tenantId Required. .PARAMETER tenantName Required. .PARAMETER appName Optional. The app name: Dime.Scheduler by default. .PARAMETER applicationPermissions Optional. The permission set to add to the app. #> param ( [Parameter(mandatory = $true, HelpMessage = "The id of the Azure tenant ")] [string] $tenantId, [Parameter(mandatory = $true, HelpMessage = "The name of the Azure tenant ")] [string] $tenantName, [Parameter(mandatory = $false, HelpMessage = "The name of the MS Entra ID App.")] [string] $appName = "Dime.Scheduler [Exchange]", [Parameter(mandatory = $false, HelpMessage = "The permission set")] [string[]] $applicationPermissions = @('Calendars.ReadWrite', 'MailboxSettings.ReadWrite', 'User.Read.All') ) $global:appId = $null; $global:clientSecretKey = $null; Function New-MSEntraIdApp { param ( [string] $displayName, [string] $tenantName ) $app = az ad app list --display-name $displayName | ConvertFrom-Json if ($app.length -eq 0) { Write-Host "MS Entra ID App '$displayName' does not exist yet. Creating..." -ForegroundColor DarkYellow $app = az ad app create ` --display-name $displayName ` --web-home-page-url "https://app.dimescheduler.com" ` --web-redirect-uris "https://app.dimescheduler.com/signin-microsoft" ` --identifier-uris "https://app.dimescheduler.com/" | ConvertFrom-Json Write-Host "MS Entra ID App '$displayName' has been created!" -ForegroundColor DarkGreen } else { Write-Host "MS Entra ID App '$displayName' already exists." -ForegroundColor DarkGreen $app = $app[0]; } Write-Host "Creating secret..." -ForegroundColor DarkYellow $date = Get-Date -Format "yyyyMMdd" $customIdentifier = "Dime.Scheduler-$date" $clientSecret = az ad app credential reset --id $app.appId --years 20 --append --query password -o tsv $global:clientSecretKey = $clientSecret $clientSecret = az ad app credential reset --id $app.appId --years 20 --append --query password -o tsv $global:clientSecretKey = $clientSecret Write-Host "Created secret!" -ForegroundColor DarkGreen # Create a service principal for the app # This is necessary to be able to grant the application the required permissions $spForApp = az ad sp create --id $app.appId $global:appId = $app.appId return $app } Function Grant-AdminConsent { param ($appId) Write-Host "Granting admin consent..." -ForegroundColor DarkYellow az ad app permission admin-consent --id $appId Write-Host "Granted admin consent!" -ForegroundColor DarkGreen } Function Add-Permissions { param ( [string] $targetServicePrincipalName, $appPermissionsRequired, $childApp, $spForApp ) $graphId = az ad sp list --query "[?appDisplayName=='Microsoft Graph'].appId | [0]" --all # Iterate Permissions array Write-Host "Retrieving role assignments objects..." $roleAssignments = [System.Collections.ArrayList]::new() foreach ($appPermission in $appPermissionsRequired) { Write-Host "Retrieving $appPermission " -ForegroundColor DarkYellow $roleAssignment = az ad sp show --id $graphId --query "appRoles[?value=='$appPermission'].id | [0]" if ($roleAssignment) { Write-Host "$roleAssignment" -ForegroundColor DarkGreen [void]$roleAssignments.Add(($roleAssignment.Replace("`"", ""))) } else { Write-Host "$appPermission was not found!" -ForegroundColor DarkYellow } } $requiredResourceAccessObjects = [System.Collections.ArrayList]::new() foreach ($roleAssignment in $roleAssignments) { [void]$requiredResourceAccessObjects.Add(@{ id = $roleAssignment type = "Role" }) } $requiredResourceAccess = @{ "resourceAppId" = $graphId.Replace("`"", "") "resourceAccess" = $requiredResourceAccessObjects } $requiredResourceAccessArray = $requiredResourceAccess | ConvertTo-Json -AsArray -Depth 6 -Compress $jsonString = ($requiredResourceAccessArray | Out-String) -replace '"', '\"' Write-Host $requiredResourceAccessArray -ForegroundColor DarkYellow az ad app update --id $childApp.appId --required-resource-accesses $jsonString Write-Host "Addded permissions to app." -ForegroundColor DarkGreen } Write-Output "" Write-Output "" Write-Output "*" Write-Output "**" Write-Output "***" Write-Output "****" Write-Output "*****" Write-Output "******" Write-Output "*******" Write-Output "********" Write-Output "*********" Write-Output "**********" Write-Output "***********" Write-Output "************" Write-Output "" Write-Output "_____ _ _____ _ _ _" Write-Output "| __ \(_) / ____| | | | | | |" Write-Output "| | | |_ _ __ ___ ___ | (___ ___| |__ ___ __| |_ _| | ___ _ __" Write-Output "| | | | | '_ ` _ \ / _ \ \___ \ / __| '_ \ / _ \/ _` | | | | |/ _ \ '__|" Write-Output "| |__| | | | | | | | __/_ ____) | (__| | | | __/ (_| | |_| | | __/ |" Write-Output "|_____/|_|_| |_| |_|\___(_)_____/ \___|_| |_|\___|\__,_|\__,_|_|\___|_|" Write-Output "" Write-Output "" Write-Output "" Write-Output "************" Write-Output "***********" Write-Output "**********" Write-Output "*********" Write-Output "********" Write-Output "*******" Write-Output "******" Write-Output "*****" Write-Output "****" Write-Output "***" Write-Output "**" Write-Output "*" Write-Output "" Write-Output "" # Login to Azure az login --tenant $tenantId # Create MS Entra ID App $app = New-MSEntraIdApp -displayName $appName -tenantName $tenantName # Add application permissions $spForApp = az ad sp list --filter "appId eq '$($app.appId)'" | ConvertFrom-Json Add-Permissions -targetServicePrincipalName 'Microsoft Graph' -appPermissionsRequired $applicationPermissions -childApp $app -spForApp $spForApp[0] Grant-AdminConsent -appId $app.appId Write-Host "" Write-Host "" Write-Host "******************" Write-Host "Copy the application id to complete the installation of Dime.Scheduler" Write-Host $global:appId Write-Host "******************" Write-Host "Copy the client secret to complete the installation of Dime.Scheduler" Write-Host "WARNING: once you close this window, you won't be able to recover the client secret." Write-Host $global:clientSecretKey Write-Host "******************" |