What Problem Does This Solve?
Someone recently asked me how they can quickly update the service account for thousands of managed resources in Privilege Secure. When they try to do that through the UI, they’re not able to quickly select all managed resources.
Rather than asking them to spend the time manually scrolling and selecting managed resources in bulk, we can use PowerShell, the SbPAMAPI PowerShell module, and Privilege Secure’s API to automate the whole process.
Locating the Service Account’s ID
First, we need to locate the ID (GUID) of the service account we want to assign to all of our resources. We can do this in Privilege Secure on the Service Accounts page with our browser’s Developer Console open to the Network tab.
Each browser is different, but in Google Chrome the Developer Console can be opened by pressing
Ctrl + Shift + I
or by opening the⋮
menu and navigating toMore Tools > Developer Tools
.
Set the Network tab’s filter to /api/v1/Credential
then click the button in the upper-left to clear old data. Now, click on the service account you want to assign to your managed resources. In the Dev Console, click on the API call and check the Response tab - the first property will be that service account’s ID, which we’ll use when making calls to Privilege Secure’s API.
Installing Privilege Secure’s PowerShell Module
Next, we need to install Privilege Secure’s PowerShell module. We can do so by navigating to the Extras
folder that’s included with each Privilege Secure download and running SbPAMPowershellModules.msi
as an administrator.
The PowerShell module needs to be installed on the computer where the PowerShell script will be run. This can be the Privilege Secure server itself, or any computer that can access Privilege Secure via a web browser.
Executing the PowerShell Script
With our service account ID in hand and Privilege Secure’s PowerShell module installed, we’re now ready to run our script.
Please review the additional instructions below the script before running it.
# Update-AllManagedResourceServiceAccounts.ps1
param(
[Parameter(Mandatory)]
[string]$npsUri,
[Parameter(Mandatory)]
[PSCredential]$userCred,
[Parameter(Mandatory)]
[string]$userCode,
[Parameter(Mandatory)]
[string]$serviceAccountId,
[switch]$UpdateAllExistingServiceAccounts
)
Import-Module SbPAMAPI -Force
# FUNCTION: Token renewal
function Get-RenewToken {
param(
[Parameter(Mandatory)]
[string]$token,
[Parameter(Mandatory)]
[string]$npsUri
)
$tokenObj = Convert-SbPAMToken $token
$expiration = Get-Date -UnixTimeSeconds $tokenObj.exp
if ($expiration -lt (Get-Date).AddMinutes(7)) {
Write-Host "$(Get-Date) Refreshing token"
$token = Invoke-SbPAMRest -Uri "$($npsUri)/api/v1/UserToken" -Token $token -ErrorAction Stop -SkipCertificateCheck
}
return $token
}
# FUNCTION: Get managed resources
function Get-AllManagedResourceHosts {
param(
[Parameter(Mandatory)]
[string]$npsUri
)
$skip = 0
$take = 10000
$MRCache = @()
if ($UpdateAllExistingServiceAccounts) {
Write-Host "$(Get-Date) Fetching ALL managed resources with a service account"
} else {
Write-Host "$(Get-Date) Only fetching host resources"
}
do {
$global:token = Get-RenewToken -token $global:token -npsUri $npsUri
$result = Invoke-SbPAMRest -Uri "$($npsUri)/api/v1/ManagedResource/Search?skip=$skip&take=$take" -Token $global:token -ErrorAction Stop -SkipCertificateCheck
if ($UpdateAllExistingServiceAccounts) {
$result.Data | ForEach-Object {
if ($null -ne $_.serviceAccountId) {
$MRCache += $_
}
}
} else {
$result.Data | ForEach-Object {
if (($null -ne $_.serviceAccountId) -and ($_.type -eq 0) ) {
$MRCache += $_
}
}
}
$skip += $take
}
while ($result.Data.Count -eq $take)
return $MRCache;
}
# FUNCTION: Update service account for resource
function Update-ManagedResourceServiceAccount {
param(
[Parameter(Mandatory)]
$resourceObj,
[Parameter(Mandatory)]
$serviceAccountId
)
$resourceObj.serviceAccountId = $serviceAccountId
$global:token = Get-RenewToken -token $global:token -npsUri $npsUri
$result = Invoke-SbPAMRest -Uri "$($npsUri)/api/v1/ManagedResource/$($_.id)" -Token $global:token -Method Put -Body (Convertto-Json $resourceObj) -ErrorAction Stop -SkipCertificateCheck
if ($? -ne $true) {
Write-Host "$(Get-Date) ERROR: $($_.Exception.Message)`n$(Get-Date) Managed resource $($resourceObj.name) service account not updated" -ForegroundColor Red
} else {
Write-Host "$(Get-Date) Updated managed resource $($resourceObj.name) service account to service account ID: $($serviceAccountId)" -ForegroundColor Green
}
}
# Create web session
$webSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
# Get user token
$global:token = Get-SbPAMToken -Credential $userCred -Uri $npsUri -WebSession $webSession -SkipCertificateCheck -ErrorAction Stop
$global:token = Get-SbPAMMfaToken -Uri $npsUri -Token $token -Code $userCode -WebSession $webSession -SkipCertificateCheck -ErrorAction Stop
# Get managed resources
$managedResources = Get-AllManagedResourceHosts -npsUri $npsUri
# Update service account for each managed resource
$managedResources | ForEach-Object {
Update-ManagedResourceServiceAccount -resourceObj $_ -serviceAccountId $serviceAccountId
}
The script can be excuted in PowerShell, such as the following example. Please note the userCred
needs to be a Privilege Secure admin user. userCode
is the user’s MFA code, and serviceAccountId
is the service account ID we found earlier.
If the user does not use MFA, the
userCode
parameter is still required. However, since the user does not have an MFA code, you can simply use any placeholder text (such as “notrequired”).
.\Update-AllManagedResourceServiceAccounts.ps1 -npsUri "https://nps-server.domain.net:6500" -userCred "domain\my_user" -userCode "notrequired" -serviceAccountId "14132595-b953-4b87-bdae-4a63d6d5d1a7"
There’s also an optional parameter that can be used when executing the script: UpdateAllExistingServiceAccounts
.
By default, the script fetches managed resources of type host but will skip other resource types such as domains. If you’d like to change the service account on all resource types that use a service account, you can add the aforementioned parameter when executing the script.
When you execute the script, you’ll be prompted for your Privilege Secure user’s password. Once that is input, the script will fetch managed resources and assign the specified service account.