VMware Workspace ONE Community
PerPilot
Contributor
Contributor

Local Administrator Password Solution (LAPS) for Workspace One

Hi all!

We have a split enviroment where our existing client machines are members of on prem AD, whereas most newer machines now are implemented with Workspace one and Azure AD. We would like to implement Local Administrator Password Solution (LAPS) on all machines. This is not a problem with the on-prem machines, but I do not know how well it will work with the machines being implemented with wso and Azure AD. Does anybody have any experience doing this, or know of an alternative solution instead of LAPS that can do the same thing on wso?

Regards,

Per

Labels (2)
0 Kudos
3 Replies
AlexAskin
Enthusiast
Enthusiast

In principal LAPS generates a random password and stores it securely in Active Directory. This can be achieved in many different ways.

 

Running a script and collecting a resulting value (eg. a new password) can be done natively in Workspace ONE using Sensors - it can use your defined data-sample intervals as scheduler or Event-based on "Login, Logout, Startup, etc".

Data is stored on the VMware Intelligence Platform, where you can delegate access to authorised personal. Soon these Sensors values will be visible directly inside the Workspace ONE UEM Admin console.

 

In case you need/want to store the passwords in a Azure Vault, you can follow this article and replace Intune Powershell execution with Workspace ONE Sensor, Product Provisioning or Scripts (coming soon): https://www.cloud-boy.be/blog/serverless-laps-with-intune-function-app-and-key-vault/ 

 

Alex

PerPilot
Contributor
Contributor

Hi Alex

Thanks very much for the info! I will look into both options.

 

Regards,

Per

0 Kudos
PerPilot
Contributor
Contributor

Hi again,

I tried out the Azure route, setting up a function app in Azure as described in https://www.cloud-boy.be/blog/serverless-laps-with-intune-function-app-and-key-vault/ and Product provisioning as the method for distributing the powershell script. I also made a small script for adding a task in Windows scheduler for running the local admin script on a monthly basis. The script is added with dependancy to the local admin script.

Although the local admin script does what its supposed to, Workspace one reports that it fails (although everything has been done), which means that the next script never gets pushed out, since the dependancy fails.

The local log file indicates that it might be because the script stops due to the user already existing, but the script continues to run, changing the password as it should, so i dont think that should make WSO report it as failed.

This is what i found in the local log file.

PS>TerminatingError(New-LocalUser): "The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: User local-admin already exists."
Local Admin 'local-admin' already exists. Changing password.

I include the script, which is unchanged from the article you provided.

# New-LocalUser is only available in a x64 PowerShell process. We need to restart the script as x64 bit first.
# Based on a template created by Oliver Kieselbach @ https://gist.github.com/okieselbach/4f11ba37a6848e08e8f82d9f2ffff516
$exitCode = 0

if (-not [System.Environment]::Is64BitProcess) {
# start new PowerShell as x64 bit process, wait for it and gather exit code and standard error output
$sysNativePowerShell = "$($PSHOME.ToLower().Replace("syswow64", "sysnative"))\powershell.exe"

$processStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$processStartInfo.FileName = $sysNativePowerShell
$processStartInfo.Arguments = "-ExecutionPolicy Bypass -File `"$PSCommandPath`""
$processStartInfo.RedirectStandardError = $true
$processStartInfo.RedirectStandardOutput = $true
$processStartInfo.CreateNoWindow = $true
$processStartInfo.UseShellExecute = $false

$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processStartInfo
$process.Start()

$exitCode = $process.ExitCode

$standardError = $process.StandardError.ReadToEnd()
if ($standardError) {
Write-Error -Message $standardError
}
}
else {
#region Configuration
# Define the userName for the Local Administrator
$userName = "local-admin"

# Azure Function Uri (containing "azurewebsites.net") for storing Local Administrator secret in Azure Key Vault
$uri = 'https://myawesomefunctionapp.azurewebsites.net/api/Set-KeyVaultSecret?code=Blahblahblah=='
#endregion


# start logging to TEMP in file "scriptname.log"
$null = Start-Transcript -Path "$env:TEMP\$($(Split-Path $PSCommandPath -Leaf).ToLower().Replace(".ps1",".log"))"

# Azure Function Request Body. Azure Function will strip the keyName and add a secret value. https://docs.microsoft.com/en-us/rest/api/keyvault/setsecret/setsecret
$body = @"
{
"keyName": "$env:COMPUTERNAME",
"contentType": "Local Administrator Credentials",
"tags": {
"Username": "$userName"
}
}
"@

# Use TLS 1.2 connection
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Trigger Azure Function.
try {
$password = Invoke-RestMethod -Uri $uri -Method POST -Body $body -ContentType 'application/json' -ErrorAction Stop
}
catch {
Write-Error "Failed to submit Local Administrator configuration. StatusCode: $($_.Exception.Response.StatusCode.value__). StatusDescription: $($_.Exception.Response.StatusDescription)"
}

# Convert password to Secure String
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force

# Create a new Local User, change the password if it already exists.
try {
New-LocalUser -Name $userName -Password $securePassword -PasswordNeverExpires:$true -AccountNeverExpires:$true -ErrorAction Stop
}
catch {
# If it already exists, catch it and continue.
if ($_.CategoryInfo.Reason -eq 'UserExistsException') {
Write-Output "Local Admin '$userName' already exists. Changing password."
$userExists = $true
}
else {
$exitCode = -1
Write-Error $_
}
}

if ($userExists) {
# Change the password of the Local Administrator
try {
Set-LocalUser -Name $userName -Password $securePassword
}
catch {
$exitCode = -1
Write-Error $_
}
}
else {
# Add the new Local User to the Local Administrators group
try {
Add-LocalGroupMember -SID 'S-1-5-32-544' -Member $userName
Write-Output "Added Local User '$userName' to Local Administrators Group"
}
catch {
$exitCode = -1
Write-Error $_
}
}

$null = Stop-Transcript
}

exit $exitCode

0 Kudos