public/provisioning.ps1
function Update-NimbusDependencies { Param( [Parameter(Mandatory = $false)] [ValidateSet('portal_nimbload_com' , 'portal_luware_cloud', 'portal_stage_nimbdev_com', 'portal_uat_nimbdev_com')] [string]$env = 'placeholder', [Parameter(Mandatory = $false)] [object]$webhookData ) Check-Module # Initialize the variables if ( $inRunbook ) { $cred = Get-AutomationPSCredential -Name nimbusCredentials $env = Get-AutomationVariable -Name nimbusEnvironment $callbackUrl = Get-AutomationVariable -Name callBackUrl $callbackUrl = [Text.Encoding]::Utf8.GetString( [Convert]::FromBase64String( $callbackUrl ) ) } else { $cred = New-CredentialsPrompt "AzureAd" } $pstnNumbers = [System.Collections.ArrayList]@() $callingBotPermissions = "Calls.Initiate.All", "Calls.InitiateGroupCall.All", "Calls.JoinGroupCall.All", "Calls.JoinGroupCallAsGuest.All", "OnlineMeetings.ReadWrite.All","Calls.AccessMedia.All" $generalBotPermissions = "Directory.Read.All", "Group.Read.All", "User.Read.All" $mediaBotPermissions = "Calls.AccessMedia.All","Calls.Initiate.All","Calls.InitiateGroupCall.All","Calls.JoinGroupCall.All","Calls.JoinGroupCallAsGuest.All" $nimbusDomain = $mapper.$env.domain $nimbusAppId = $mapper.$env.nimbusAppId $mediaBotId = $mapper.$env.mediaBotId New-AzureAdLogin $cred New-MsolLogin $cred New-SkypeOnlineLogin $cred $webSession, $tenant = New-NimbusLogin -domain $nimbusDomain # Retrieve pending changes if ( $inRunbook ) { try { $uri = "https://{0}/api/provisioning/v1/tenants/{1}/service-details/{2}" -f $nimbusDomain, $tenant, $webhookData.teamId $teams = Invoke-WebRequest -WebSession $webSession -Uri $uri -UseBasicParsing | ConvertFrom-Json } catch { Write-Error "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Error "Could not get changes for your tenant. Exiting." Write-Error $_.Exception.Message Cleanup-Environment -exitCode 1 } $teamJson = $teams | ConvertTo-Json -Compress -ErrorAction SilentlyContinue $webhookDataJson = $webhookData | ConvertTo-Json -Compress -ErrorAction SilentlyContinue if ( -not $teams -or ( Compare-Object $teamJson $webhookDataJson ) ) { Write-Error "Configuration mismatch, sending failure email." Write-Error $webhookDataJson $webhookData | Add-Member -MemberType NoteProperty -Name failed -Value $true -Force Invoke-RestMethod ` -Method:Post ` -UseBasicParsing ` -Uri $callbackUrl ` -Body ( $webhookData | ConvertTo-Json -Compress -Depth 5 ) ` -ContentType 'application/json' Cleanup-Environment -exitCode 1 } } else { try { $teams = Invoke-WebRequest ` -WebSession $webSession ` -Uri "https://$nimbusDomain/api/facade/v1/provisioning/tenants/$tenant/service-details" | ConvertFrom-Json } catch { Write-Output "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Output "Could not get changes for your tenant. Exiting" Cleanup-Environment -exitCode 1 } } try { Write-Output "Granting permissions for main Nimbus App" Update-ServicePrincipal -appId $nimbusAppId -permissions $generalBotPermissions Update-ServicePrincipal -appId $mediaBotId -permissions $mediaBotPermissions Write-Output " [Done]" } catch { Write-Output "[Failed]" } if ( Read-HostProxy "Would you like to re-grant all permissions to all the bots configured in your tenant? (Default is No)" ) { try { $botIds = Invoke-WebRequest ` -WebSession $webSession ` -Uri "https://$nimbusDomain/api/facade/v1/provisioning/tenants/$tenant/bot-ids" | ConvertFrom-Json Write-Output "Granting permissions for all $($botIds.Length) configured bots in your tenant" foreach ( $botId in $botIds ) { Update-ServicePrincipal -appId $botId -permissions $callingBotPermissions Set-CsApplicationMeetingConfiguration -AllowRemoveParticipantAppIds @{Add="$($botId)"} Write-Output "Bot $botId - All permissions were granted" } Write-Output " [Done]" } catch { Write-Error ( $_.Exception | Format-List -Force | Out-String ) -ErrorAction Continue Write-Error ( $_.InvocationInfo | Format-List -Force | Out-String ) -ErrorAction Continue Write-Output "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Output "Could not get existing botIds. Will continue with pending changes." } } else { Write-Output "Skip re-granting all permissions" } # Apply updates (prompt user if using interactive mode) Write-Output "Fetched Changes for $($teams | Measure-Object | Select-Object -ExpandProperty count) Teams..." foreach ($team in $teams) { Write-Output "=============================================================" Write-Output "=============================================================" Write-Output "Team: $($team.teamName)" Write-Output "-------------------------------------------------------------" if ( -not [string]::IsNullOrEmpty($team.applicationId) -and $team.isSuspended ) { if ( Read-HostProxy "Would you like to delete the ApplicationInstance of '$($team.teamName)'? The team is suspended. (Default is No)" ) { Write-Output "Removing ApplicationInstance for '$($team.teamName)'..." try { Remove-AzureADUser -ObjectId $team.applicationId -ErrorAction SilentlyContinue Sync-CsOnlineApplicationInstance -ObjectId $team.applicationId -ErrorAction SilentlyContinue } catch { Write-Output "[Failed]" Write-Output "Application Instance doesn't exist anymore" } finally { $team.applicationId = $null Invoke-WebRequest ` -WebSession $webSession ` -Method:Post ` -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" ` -ContentType "application/json" ` -Body ($team | ConvertTo-Json) | Out-Null Write-Output " [Done]" } } else { Write-Output "Skip removing ApplicationInstance for '$($team.teamName)'" } } elseif ( [string]::IsNullOrEmpty($team.applicationId) ) { Write-Output "Values to be set:" Write-Output ($team.teamServiceDetails | Format-Table | Out-String) if ([string]::IsNullOrEmpty($team.teamServiceDetails.upn)) { Write-Output "No Upn is set. Please configure this team correctly." Write-Output "=============================================================" continue } if ( Read-HostProxy "Would you like to create an ApplicationInstance for '$($team.teamName)'? (Default is No)" ) { try { Write-Output "Granting permissions for Calling Bot Application" Update-ServicePrincipal -appId $team.botId -permissions Set-CsApplicationMeetingConfiguration -AllowRemoveParticipantAppIds @{Add="$($team.botId)"} Write-Output " [Done]" } catch { Write-Output "[Failed]" } Write-Output "Creating ApplicationInstance for '$($team.teamName)'..." try { try { $app = New-CsOnlineApplicationInstance -UserPrincipalName $team.teamServiceDetails.upn -DisplayName $team.teamServiceDetails.name -ApplicationId $team.botId } catch [System.Management.Automation.RemoteException] { if ($Error[0].Exception -match "provided UserPrincipalName is already used") { try { Write-Output " Upn already used. Generating new one..." $team.teamServiceDetails = Invoke-WebRequest ` -WebSession $webSession ` -Uri "https://$nimbusDomain/api/teammanager/v1/tenants/$tenant/teams/$($team.teamId)/service-details/regenerate-upn" | ConvertFrom-Json Write-Output " [Done]" } catch { Write-Output "[Failed]" Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Output "[Failed]" continue } $app = New-CsOnlineApplicationInstance -UserPrincipalName $team.teamServiceDetails.upn -DisplayName $team.teamServiceDetails.name -ApplicationId $team.botId } else { Cleanup-Environment -exitCode 1 } } Sync-CsOnlineApplicationInstance -ObjectId $app.ObjectId $team.applicationId = $app.ObjectId $isDone = Update-Pstn -teamToCheck $team if ( -not $isDone ) { $pstnNumbers.Add($team) | Out-Null Write-Output "[Pending]" Write-Output " Could not yet complete PSTN number assignment will try again at the end." } else { Invoke-WebRequest ` -WebSession $webSession ` -Method:Post ` -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" ` -ContentType "application/json" ` -Body ($team | ConvertTo-Json) | Out-Null Write-Output " [Done]" } } catch [System.Management.Automation.RemoteException] { Write-Output "[Failed]" Write-Output " Could not create ApplicationInstance $($_.Exception)" Write-Output " Please check your configuration." continue } catch { Write-Output "[Failed]" Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Output " An Error occurred sending the update to Nimbus." continue } } else { Write-Output "Skip creating ApplicationInstance for '$($team.teamName)'" } } else { Write-Output "Values to be updated:" Write-Output ( $team.teamServiceDetails | Format-Table | Out-String ) if ( Read-HostProxy "Would you like to update the ApplicationInstance for '$($team.teamName)'? (Default is No)" ) { try { Write-Output "Updating ApplicationInstance for '$($team.teamName)'..." if ( -not [string]::IsNullOrEmpty($team.teamServiceDetails.upn) ) { try { Write-Output " Setting new UPN..." Set-MsolUserPrincipalName -ObjectId $team.applicationId -NewUserPrincipalName $team.teamServiceDetails.upn Write-Output " [Done]" } catch [Microsoft.Online.Administration.Automation.MicrosoftOnlineException] { if ($_.Exception -match "user principal name already exists") { Write-Output "[Failed]" Write-Output " $($_.Exception)" try { Write-Output " Regenerating UPN..." $team.teamServiceDetails = Invoke-WebRequest ` -WebSession $webSession ` -Uri "https://$nimbusDomain/api/teammanager/v1/tenants/$tenant/teams/$($team.teamId)/service-details/regenerate-upn" | ConvertFrom-Json Set-MsolUserPrincipalName -ObjectId $team.applicationId -NewUserPrincipalName $team.teamServiceDetails.upn Write-Output " [Done]" } catch { Write-Output "[Failed]" Write-Output " $($_.Exception)" $team.teamServiceDetails.PsObject.Properties.Remove('upn') } } else { Write-Output "[Failed]" Write-Output " $($_.Exception)" $team.teamServiceDetails.PsObject.Properties.Remove('upn') } } } if ( -not [string]::IsNullOrEmpty($team.teamServiceDetails.name) ) { Set-CsOnlineApplicationInstance -Identity $team.applicationId -DisplayName $team.teamServiceDetails.name | Out-Null } $isDone = Update-Pstn -teamToCheck $team Sync-CsOnlineApplicationInstance -ObjectId $team.applicationId if ( -not $isDone ) { $pstnNumbers.Add($team) | Out-Null Write-Output "[Pending]" Write-Output " Could not yet complete PSTN number assignment will try again at the end." } else { Invoke-WebRequest ` -WebSession $webSession ` -Method:Post ` -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" ` -ContentType "application/json" ` -Body ( $team | ConvertTo-Json -Compress -Depth 5 ) | Out-Null Write-Output " [Done]" } } catch [System.Management.Automation.RemoteException] { Write-Output "[Failed]" Write-Output " Could not update ApplicationInstance $($_.Exception)" Write-Output " Please check your configuration." continue } catch [System.Net.WebException] { Write-Output "[Failed]" Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)" Write-Output " An Error occurred sending the update to Nimbus." continue } catch { Write-Output "[Failed]" Write-Output " An unexpected error occurred: $($_.Exception.Response.StatusCode.Value__)" } } else { Write-Output "Skip updating ApplicationInstance for '$($team.teamName)'" } Write-Output "=============================================================" } Write-Output "" Write-Output "" } $tries = 0 while ( $pstnNumbers.Count -gt 0 -and $tries -lt 10 ) { Write-Output "Retry to set pending PSTN number changes in 1 minute." 0..12 | Foreach-Object { Write-Output "." Start-Sleep -Seconds 5 } for ( $i = 0; $i -lt $pstnNumbers.Count; $i++ ) { $team = $pstnNumbers[$i] Write-Output "=============================================================" Write-Output "Team '$($team.teamName)'" $isDone = Add-PhoneNumber -ObjectId $team.applicationId -PstnNumber $team.teamServiceDetails.pstnNumber if ( $isDone ) { $pstnNumbers.RemoveAt($i) Update-NimbusServicePrincipal -team $team Write-Output " [Done]" if ( $pstnNumber.Count -eq 0 ) { break } $i-- } else { if ( $tries -eq 9 ) { Write-Output "[Failed]" } else { Write-Output "[Pending]" } } } $tries++ } if ( $pstnNumbers.Count -gt 0 ) { Write-Output "Unfortunately, not all numbers could be set." foreach ( $team in $pstnNumbers ) { $team.teamServiceDetails.PsObject.Properties.Remove('pstnNumber') Update-NimbusServicePrincipal -team $team } } Cleanup-Environment } # SIG # Begin signature block # MIINMwYJKoZIhvcNAQcCoIINJDCCDSACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUZEKF6M11clG2FTQZFpmy30I8 # 4pmgggpxMIIFGjCCBAKgAwIBAgIQAZyhpG3mRP4nVXpkMz8jhDANBgkqhkiG9w0B # AQsFADB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBTSEEyIEhp # Z2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTAeFw0xOTA1MjEwMDAwMDBaFw0y # MjA1MjUxMjAwMDBaMFkxCzAJBgNVBAYTAkNIMRAwDgYDVQQIDAdaw7xyaWNoMRAw # DgYDVQQHDAdaw7xyaWNoMRIwEAYDVQQKEwlMdXdhcmUgQUcxEjAQBgNVBAMTCUx1 # d2FyZSBBRzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANx3Pfx2CKUz # Ot9W7Scb5rrrnI7m7jOkVG4X2Owj+hJJuEjTA3wIfA/6ay4Wa/Qv+MMdlsv6NRt4 # TgYUMRexmfGgKT7iy4AIebBuyS1lg2gmT/25xGtqO3TPqfhstLNEfcKMaMM2ZEZm # vCZbiAs3zP1G2oS94DWcCnDCjmPPll30nlOig+ZQGqBuhvNiZ/DGhnYRtrHoRx40 # 7iZjcixgPjkey9IGN6WEUYnhJ712npXTWWUIpiSZ2U475DxLWbEQ7bPHnLsivVNg # 59f4Jnf8pyqhNelrbGrTeLOuF4JyE5a8Mt2Bc58NCLWT4I9bz8N/7Uk3+RZFtD3O # Cv4nO2h7mG0CAwEAAaOCAb8wggG7MB8GA1UdIwQYMBaAFGedDyAJDMyKOuWCRnJi # /PHMkOVAMB0GA1UdDgQWBBQthLJG1fU0R5j9FwY+vNZOT2lf4DAOBgNVHQ8BAf8E # BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwbQYDVR0fBGYwZDAwoC6gLIYqaHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtY3MtZzEuY3JsMDCgLqAshipo # dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1jcy1nMS5jcmwwTAYDVR0g # BEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGln # aWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYgGCCsGAQUFBwEBBHwwejAkBggrBgEF # BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFIGCCsGAQUFBzAChkZodHRw # Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5j # ZUNvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD # ggEBAEl5ctCYW1yDBEcpCwfycyG6vhbpQ8U2wfOQeQI5DmXImLS3spcyXO+Xfn13 # Eh/BL0gXFIi1ybM0wRG/EimU1ag/uQpCtsTRWfq2vJ96LqLf8UxRYGVw+N+IM/8e # dXAKLexYb/ta4cvByjbJpoiJAJtYN32OclXRD5ph8yehuflmu+rw9TCVuPCa7hkO # mah1L3n59tGneFGd9ZbWvqknQUAZcuKQrOofTKDb9oZKYjk2JJF7aTcjnHMuDo/X # t+uHNCmhAuPyEy5Fa+RwdFptPLhudGH3WtNr4+5As2UsBDxm3gHxCiTUMIdnXChj # 9jLvqhx3P5Rtsl4VZbBcqy/nqo4wggVPMIIEN6ADAgECAhALfhCQPDhJD/ovZ5qH # oae5MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRp # Z2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAw # WhcNMjgxMDIyMTIwMDAwWjB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl # cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdp # Q2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTCCASIwDQYJ # KoZIhvcNAQEBBQADggEPADCCAQoCggEBALRKXn0HD0HexPV2Fja9cf/PP09zS5zR # Df5Ky1dYXoUW3QIVVJnwjzwvTQJ4EGjI2DVLP8H3Z86YHK4zuS0dpApUk8SFot81 # sfXxPKezNPtdSMlGyWJEvEiZ6yhJU8M9j8AO3jWY6WJR3z1rQGHuBEHaz6dcVpbR # +Uy3RISHmGnlgrkT5lW/yJJwkgoxb3+LMqvPa1qfYsQ+7r7tWaRTfwvxUoiKewpn # JMuQzezSTTRMsOG1n5zG9m8szebKU3QBn2c13jhJLc7tOUSCGXlOGrK1+7t48Elm # p8/6XJZ1kosactn/UJJTzD7CQzIJGoYTaTz7gTIzMmR1cygmHQgwOwcCAwEAAaOC # AeEwggHdMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMH8GCCsGAQUFBwEBBHMwcTAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEkGCCsGAQUFBzAChj1odHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0 # MIGPBgNVHR8EgYcwgYQwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9j # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5j # cmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBz # Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYEFGed # DyAJDMyKOuWCRnJi/PHMkOVAMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoIAu9j # ZCvDMA0GCSqGSIb3DQEBCwUAA4IBAQBqDv9+E3wGpUvALoz5U2QJ4rpYkTBQ7Myf # 4dOoL0hGNhgp0HgoX5hWQA8eur2xO4dc3FvYIA3tGhZN1REkIUvxJ2mQE+sRoQHa # /bVOeVl1vTgqasP2jkEriqKL1yxRUdmcoMjjTrpsqEfSTtFoH4wCVzuzKWqOaiAq # ufIAYmS6yOkA+cyk1LqaNdivLGVsFnxYId5KMND66yRdBsmdFretSkXTJeIM8ECq # XE2sfs0Ggrl2RmkI2DK2gv7jqVg0QxuOZ2eXP2gxFjY4lT6H98fDr516dxnZ3pO1 # /W4r/JT5PbdMEjUsML7ojZ4FcJpIE/SM1ucerDjnqPOtDLd67GftMYICLDCCAigC # AQEwgYowdjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG # A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTE1MDMGA1UEAxMsRGlnaUNlcnQgU0hBMiBI # aWdoIEFzc3VyYW5jZSBDb2RlIFNpZ25pbmcgQ0ECEAGcoaRt5kT+J1V6ZDM/I4Qw # CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw # IwYJKoZIhvcNAQkEMRYEFHYE4h9LrHvAqC6T8HyUYjF+i6s7MA0GCSqGSIb3DQEB # AQUABIIBAJMVVZ589yPsqC+s2pY05HYVL9UkptjjpR/nvXl8vXKk5z9zd5HPJnbh # sbCDdMBxQo3avCwi7ND7w0l2bqYNYvHgQInrw9qRXuIgxL/tPCCJXcipWpUtlBxg # H7mdE53RBL7imVUkWdXPW5l7pKRROmSPwwYWske95zQBNA0z1/NF5/5+M0i8tndJ # hh+7g+qgM+ckyWLnN0WUjHQ+hXHg6Ye6EnRmgpcWFrDvFEaCtRJrP3j1aPYuriHF # pwyVI4zPp7/eUfAoXo1prVIKpXJe8ZirHAHuJLT1DdUwk92hUU+cRglZrBkQIWQY # corRclbE+sfWygsE0eBgMzLjUPhHt1A= # SIG # End signature block |