Skip to content

Instantly share code, notes, and snippets.

@mozziemozz
Last active March 28, 2022 16:32
Show Gist options
  • Save mozziemozz/ce70f39f720bf17632f60a3d6b1be110 to your computer and use it in GitHub Desktop.
Save mozziemozz/ce70f39f720bf17632f60a3d6b1be110 to your computer and use it in GitHub Desktop.
Remotely change the opt in status of a Teams Call Queue Agent
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)][String]$UserId, # AAD User Object Id
[Parameter(Mandatory=$false)][String]$UserName, # AAD User Name
[Parameter(Mandatory=$false)][String]$TenantName, #your primary domain or *.onmicrosoft.com domain
[Parameter(Mandatory=$false)][String]$CallQueueId, # Call Queue Id
[Parameter(Mandatory=$false)][ValidateSet("OptIn","OptOut")][String]$Action,
[Parameter(Mandatory=$false)][Switch]$QueryStatusOnly,
[Parameter(Mandatory=$false)][Switch]$MFA
)
if (Test-Path ".\creds_$UserName.txt") {
$passwordHash = Get-Content -Path ".\creds_$UserName.txt"
$secureStringPassword = $passwordHash | ConvertTo-SecureString
$password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureStringPassword))
}
else {
$secureStringPassword = Read-Host "Please enter the password you would like to encrypt." -AsSecureString
$passwordHash = $secureStringPassword | ConvertFrom-SecureString
Set-Content -Path ".\creds_$UserName.txt" -Value $passwordHash
$password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureStringPassword))
}
if ($MFA) {
if (Test-Path ".\mfa_$UserName.txt") {
$passwordHash = Get-Content -Path ".\mfa_$UserName.txt"
$secureStringPassword = $passwordHash | ConvertTo-SecureString
$secret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureStringPassword))
}
else {
$secureStringPassword = Read-Host "Please enter the mfa secret you would like to encrypt." -AsSecureString
$passwordHash = $secureStringPassword | ConvertFrom-SecureString
Set-Content -Path ".\mfa_$UserName.txt" -Value $passwordHash
$secret = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureStringPassword))
}
}
try {
if (Test-Path ".\token_$UserName.txt") {
$AADBearerToken = Get-Content -Path ".\token_$UserName.txt"
$Headers = @{
Authorization = $AADBearerToken
}
}
else {
$Headers = $null
}
Invoke-RestMethod -Uri "https://api.interfaces.records.teams.microsoft.com/Teams.VoiceApps/cq-agents/$userId" -Method Get -Headers $Headers -ContentType "application/json" -ErrorAction Stop > $null
Write-Host "Token is valid." -ForegroundColor Green
}
catch {
Write-Host "Token does not exist or is expired. Acquiring new one... Please log in with your account..." -ForegroundColor Yellow
$SendKeys = {
param(
[Parameter(Mandatory=$false)][String]$UserName,
[Parameter(Mandatory=$false)][String]$Password,
[Parameter(Mandatory=$false)][String]$secret
)
$wshell = New-Object -ComObject wscript.shell
$wshell.AppActivate('AAD User Login')
Start-Sleep 3
$wshell.SendKeys("$username~")
Start-Sleep 3
$wshell.SendKeys("$password~")
if ($secret) {
Start-Sleep 3
$otpGenerationScript = (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/mozziemozz/TOTPPowerShellModule/master/TOTP/totp.ps1").Replace("New-Alias -Name otp -Value Get-Otp","Get-Otp -SECRET $secret")
$otp = Invoke-Expression $otpGenerationScript
Start-Sleep 3
$wshell.SendKeys("$otp~")
}
Start-Sleep 3
$wshell.SendKeys("~")
}
Start-Job -ScriptBlock $SendKeys -ArgumentList $UserName, $Password, $secret
Add-Type -AssemblyName System.Web
$WebResource = "https://api.interfaces.records.teams.microsoft.com"
$redirectUrl = "https://teams.microsoft.com/go"
$client_id = "5e3ce6c0-2b1f-4285-8d4b-75ee78787346"
$scope = "48ac35b8-9aa8-4d74-927d-1f4a14a0b239%2F.default%20openid%20profile"
$nonce = [guid]::NewGuid().GUID
$url = "https://login.microsoftonline.com/$TenantName/oauth2/authorize?response_type=token&scope=$scope&redirect_uri=" +
[System.Web.HttpUtility]::UrlEncode($redirectUrl) +
"&client_id=$client_id" +
"&prompt=login" + "&nonce=$nonce" + "&resource=" + [System.Web.HttpUtility]::UrlEncode($WebResource) + "&state=12345" #here
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object -TypeName System.Windows.Forms.Form -Property @{ Width = 440; Height = 640 }
$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{ Width = 420; Height = 600; Url = ($url) }
$DocComp = {
$Global:uri = $web.Url.AbsoluteUri
if ($Global:Uri -match "error=[^&]*|access_token=[^&]*") { $form.Close() }
}
$web.ScriptErrorsSuppressed = $true
$web.Add_DocumentCompleted($DocComp)
$form.Controls.Add($web)
$form.Text = "AAD User Login"
$form.Add_Shown({ $form.Activate() })
$form.ShowDialog() | Out-Null
$Script:Token = [Web.HttpUtility]::ParseQueryString(($web.Url -replace '^.*?(access_token.+)$','$1'))['access_token']
$AADBearerToken = ('Bearer {0}' -f $Script:Token)
#$AADBearerToken
Set-Content -Path ".\token_$UserName.txt" -Value $AADBearerToken
$Headers = @{
Authorization = $AADBearerToken
}
}
if ($QueryStatusOnly) {
# Get Opt In Status
$RequestGet = (Invoke-RestMethod -Uri "https://api.interfaces.records.teams.microsoft.com/Teams.VoiceApps/cq-agents/$userId" -Method Get -Headers $Headers -ContentType "application/json").AgentCallQueuesSettings
$RequestGet | Where-Object {$_.Id -eq $callQueueId}
}
else {
# Get Opt In Status
$RequestGet = (Invoke-RestMethod -Uri "https://api.interfaces.records.teams.microsoft.com/Teams.VoiceApps/cq-agents/$userId" -Method Get -Headers $Headers -ContentType "application/json").AgentCallQueuesSettings
$cqFriendlyName = ($RequestGet | Where-Object {$_.Id -eq $callQueueId}).Name
switch ($Action) {
OptIn {
$setAction = $true
$setActionFriendly = "opted in"
}
OptOut {
$setAction = $false
$setActionFriendly = "opted out"
}
Default {}
}
if (($RequestGet | Where-Object {$_.Id -eq $CallQueueId}).OptIn -eq $setAction) {
if ($setAction -eq $true) {
Write-Host "User already $setActionFriendly for $cqFriendlyName." -ForegroundColor Yellow
}
else {
Write-Host "User already $setActionFriendly for $cqFriendlyName." -ForegroundColor Yellow
}
}
else {
($RequestGet | Where-Object {$_.Id -eq $callQueueId}).OptIn = $setAction
$payload = $RequestGet | ConvertTo-Json
# Set Opt In Status
try {
Invoke-RestMethod -Uri "https://api.interfaces.records.teams.microsoft.com/Teams.VoiceApps/cq-agents/$userId" -Body $payload -Method Put -Headers $Headers -ContentType "application/json"
Write-Host "User successfully $setActionFriendly for $cqFriendlyName." -ForegroundColor Green
}
catch {
Write-Host "Error while changing user to $setActionFriendly for $cqFriendlyName." -ForegroundColor Red
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment