Leveling up Microsoft Teams Rooms to Enterprise-Grade Automated Password Rotation with Workspace ONE

Leveling up Microsoft Teams Rooms to Enterprise-Grade Automated Password Rotation with Workspace ONE

Microsoft Teams Rooms to Enterprise

Microsoft Teams Rooms are an area I have been working on quite a bit lately. Outside of the fact, that people have learned to embrace Microsoft Teams and its part in Office 365 eco-system. they are very challenging in how they are designed. Today, we will cover how to leverage Workspace ONE (or any MDM for that fact) to elevate their password rotations. Currently, all password changes need to be made manually which is a major problem. First, we’ll discuss the problem itself and then move onto the three parts of a great solution that leverages CyberArk (since that is a common trend in the Enterprise today).

The Problem with Microsoft Teams Rooms Password Rotation

Today, if you want to change the password on a Teams Room voice you go into this screen below:

The major conflict that you have is that Microsoft’s requirements for Teams Rooms states you should not allow the resource account’s password as mentioned here. Those of us who work in an enterprise know that is not feasible. Their guidance:

Anyways, moving on we know that’s a problem, so let’s move into how do you actually do it.

Microsoft’s Supported Path for Changing Teams Rooms

Now that we know that Microsoft doesn’t want you to change passwords even though you HAVE to change passwords, let’s discuss this a bit more. So, outside of using a keylogger how would you rotate the password itself?

In Microsoft’s article here, they cover how you change settings on a Teams Room device. Basically, you create a XML config file (SkypeSettings.xml) and drop it in this location:


Briefly, here are a few of the things you can change with that file:

  • Change Wallpaper
  • Enable/Disable Whiteboard
  • A/V equipment configuration
  • Meeting Modes (SfB, Teams, etc)
  • Enabling/Disabling Front Row
  • Resolution
  • Usernames/Passwords

So basically, you can see that you can specify in the XML file what the username and password are like so:

    <ConfigureDomain>domain1, domain2</ConfigureDomain>

So that seems easy right? No big deal? Let’s discuss the real problem:

As you can see from above, our first real problem is that it’s the chicken and the egg. You FIRST must tell the MTR what the new password is, before ACTUALLY changing the password because as you can see it must FIRST log into Teams before it can process the settings file. So inevitably, the solution isn’t as simple as you might think.

Additionally, you need reboots because the file can only be consumed on a restart. The other challenge you deal with is that these devices (by design) must not be domain joined because companies like Polycom go Local GPO heavy to setup/configure/build these machines. That is a challenge on its own. Let’s cover the code that we use to make the magic happen.

Scripting the Proper Solution to Teams Rooms Password Rotation

Building the SkypeSettings.xml File

The first thing we need to do is create the SkypeSettings.xml file and set the username to a text file, which will be used later on by the other scripts. The script will evolve as they add new things to the SkypeSettings.xml like recent additions that let you block whiteboard, front row, etc.

An interesting piece of information is you need the username.txt file because once the device can no longer log into Teams it removes the username from the config JSON file.

##Create the XML File##
New-Item C:\temp\SkypeSettings.xml -ItemType File -Force
##Sets the XML File with Baseline Settings##
Set-Content C:\temp\SkypeSettings.xml '<SkypeSettings>

##Stores the Username in a text file from the config.json settings file##
$Username = Get-Content C:\Users\Skype\AppData\Local\Packages\Microsoft.SkypeRoomSystem_8wekyb3d8bbwe\LocalCache\Roaming\Microsoft\Teams\desktop-config.json
$JSONObject = ConvertFrom-Json -InputObject $Username
$Username = $JSONObject.upnWindowUserUpn
$Username | Out-File C:\temp\username.txt

##Updates the SkypeSettings.xml file with the username out of the desktop-config.json file##
$SkypeSettings = Get-Content C:\temp\SkypeSettings.xml
$SkypeSettings = $SkypeSettings -replace "<ExchangeAddress></ExchangeAddress>", ("<ExchangeAddress>" + $Username + "</ExchangeAddress>") -replace "<SkypeSignInAddress></SkypeSignInAddress>", ("<SkypeSignInAddress>" + $Username + "</SkypeSignInAddress>")
$SkypeSettings | Out-File C:\temp\SkypeSettings.xml -Force

Building the Password and Updating SkypeSettings.xml File

The second part of the solution involves writing a script that will do a few things:

  • Create the New Password
  • Update SkypeSettings.xml file and setting the new password
  • Setting permissions on the file
  • Creating a scheduler to automate this every 85 days (which will force the device at 1 AM to work its magic and reboot)

Now that you see the requirements, you can check out the code below. I have spent a bunch of time refining the code and accounting for stuff like not being able to upload files. Now the code creates the file and populates it on the fly, which is probably more efficient:

New-Item C:\temp\GenerateMTRPassword.ps1 -ItemType File -Force
Set-Content C:\temp\GenerateMTRPassword.ps1 '##Generate New Random Password and Save to Text File##
Add-Type -AssemblyName System.Web
$NewPassword = [System.Web.Security.Membership]::GeneratePassword(16,3)
New-Item -Path C:\temp\newpassword.txt -Value $NewPassword -Force'
##Stage the Config File##
New-Item -Path C:\temp -Name staging -ItemType directory -Force
Copy-Item -Path C:\temp\SkypeSettings.xml -Destination C:\temp\staging\SkypeSettings.xml
$SkypeUsername = Get-Content C:\Users\Skype\AppData\Local\Packages\Microsoft.SkypeRoomSystem_8wekyb3d8bbwe\LocalCache\Roaming\Microsoft\Teams\desktop-config.json
$JSONObject = ConvertFrom-Json -InputObject $SkypeUsername
$UPN = $JSONObject.upnWindowUserUpn
##Capture the Password and Username##
$SkypeSettings = Get-Content C:\temp\staging\SkypeSettings.xml
$SkypeSettings = $SkypeSettings -replace "<ExchangeAddress></ExchangeAddress>", ("<ExchangeAddress>" + $UPN + "</ExchangeAddress>") -replace "<SkypeSignInAddress></SkypeSignInAddress>", ("<SkypeSignInAddress>" + $UPN + "</SkypeSignInAddress>") -replace "<Password></Password>", ("<Password>" + $NewPassword + "</Password>") 
$SkypeSettings | Out-File C:\temp\staging\SkypeSettings.xml -Force
Move-Item -Path C:\temp\staging\SkypeSettings.xml -Destination C:\Users\Skype\AppData\Local\Packages\Microsoft.SkypeRoomSystem_8wekyb3d8bbwe\LocalState\SkypeSettings.xml -Force
$fileSystemRights = "FullControl"
$type = "Allow"
$fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type
$fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList
$NewAcl = Get-Acl -Path "C:\Users\Skype\AppData\Local\Packages\Microsoft.SkypeRoomSystem_8wekyb3d8bbwe\LocalState\SkypeSettings.xml"
Set-Acl -Path "C:\Users\Skype\AppData\Local\Packages\Microsoft.SkypeRoomSystem_8wekyb3d8bbwe\LocalState\SkypeSettings.xml" -AclObject $NewAcl'

##Setup Scheduler
$Time = New-ScheduledTaskTrigger -Daily -DaysInterval 85 -At 1am
$action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "C:\temp\GenerateMTRPassword.ps1"
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -WakeToRun
Register-ScheduledTask -Action $action -TaskName "Generate Password" -Trigger $time -Settings $settings -User "System" -Force

Rotate the Password in CyberArk and Reboot Once More

When the MTR does its automatic 2 AM reboot, the password change is now in effect at the Teams level (which means the MTR can no longer log into Teams). Now, we leverage one last scheduler/script to update the password in AD and remove the password file. This reboot at 3 AM, will complete the entire process:

##Get Username##
$username = Get-Content C:\temp\username.txt
$CyberArkUsername = CyberArkMTRPolicyName + $Username
##Retrieve Local Account Password##
$localpasswordretrieval = Invoke-RestMethod -Method Get -Uri https://cyberarkURL/AIMWebService/Api/Accounts?AppID=VAULTNAME&Object=PolicyName-ServiceAccountName
$localpassword = $localpasswordretrieval.content
$EscapedPassword = [System.Security.SecurityElement]::Escape($localpassword)

$AuthBody = @{username=SERVICEACCOUNTNAME;password=$EscapedPassword} | ConvertTo-Json
$CyberArkAuthToken = Invoke-RestMethod -Method Post -Uri https://cyberarkURL/api/auth/Ldap/logon -Body $AuthBody -ContentType "application/json"

##Get the New Password##
$NewPassword = Get-Content C:\temp\newpassword.txt

##Get Account ID##
$header = @{"Authorization" = $CyberArkAuthToken}
$body = @{"NewCredentials" = $NewPassword}
$AccountID = Invoke-RestMethod -Uri https://cyberarkURL/passwordvault/api/Accounts?$CyberArkUsername -Headers $header
$UserID = $AccountID.value.id
##Change Password##
Invoke-RestMethod -Method Post -Uri https://cyberarkURL/passwordvault/api/Accounts/$UserID/Password/Update -Headers $header -Body $body

##Delete Password File##
##Remove-Item -Path C:\temp\newpassword.txt -Force


##Setup Scheduler
$Time = New-ScheduledTaskTrigger -Daily -DaysInterval 85 -At 3am
$action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "C:\temp\RotatePasswordCyberArk.ps1"
$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -WakeToRun
Register-ScheduledTask -Action $action -TaskName "Rotate Password" -Trigger $time -Settings $settings -User "System" -Force

Bringing it All Together with Workspace ONE and Freestyle Orchestrator

So in my previous scripts, the reason that I had to build the XML file in-flight is because Freestyle Orchestrator doesn’t support files directly. The reason I wound up using Workspace ONE for my MTRs is that the MTRs cannot be domain-joined so I felt it would be best to treat these devices like external devices/BYOD devices.

My focus with Freestyle Orchestrator is starting with a check condition to ensure the desktop-json file exists (I’ve found it’s usually missing):

Once you achieve that, you can run scripts in a row:

Additionally, if you want to make things more robust you could also add in additional check conditions, like:

Overall, with all of this you can build a really compelling and enterprise-grade solution that eliminates the manual process of rotating passwords.

Final Thoughts

Hopefully, this information will make life much easier for those of you working with Microsoft Teams Rooms. It is a painful experience to do this manually. Imagine having to physically touch 300 rooms. This should save some substantial time and make life much easier for everyone moving forward.



Social Media

Get The Latest Updates

Subscribe To Our Weekly Newsletter

No spam, notifications only about the latest posts and updates.