$pamServer = "1.2.3.4" # either FQDN or IP address $oldPVP = "OldPvp" # name of the PVP to change from $newPVP = "NewPvp" # name of the PVP to change to Start-Transcript -OutputDirectory $PSScriptRoot -NoClobber # This section is to prevent errors when connecting to a PAM system that uses a self signed certificate. if (-not ([System.Management.Automation.PSTypeName]"TrustEverything").Type) { Add-Type -TypeDefinition @" using System.Net.Security; using System.Security.Cryptography.X509Certificates; public static class TrustEverything { private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } public static void SetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidationCallback; } public static void UnsetCallback() { System.Net.ServicePointManager.ServerCertificateValidationCallback = null; } } "@ } [TrustEverything]::SetCallback() # generate a credential object if (-not $CliCred) { $CliCred = Get-Credential -Message "Enter your PAM username and password" } # set the CLI url $Url = "https://$pamServer/cspm/servlet/adminCLI" Function getPvpId($pvpName) { # Create our request body as a hashtable $request = @{ "adminUserID" = $CliCred.UserName "adminPassword" = $CliCred.GetNetworkCredential().Password "authentication" = "CSPM" "cmdName" = "searchPasswordViewPolicy" "PasswordViewPolicy.name" = $pvpName } write-host "Retrieving the PVP id for $pvpName..." # Make the API call and store the XML results [xml]$results = Invoke-WebRequest -Uri $Url -Body $request -Method Get # The actual results are stored as XML data in a cdata section of the parent xml [xml]$results = $results.'cw.appMessage'.content.'#cdata-section' # The PVP's are nodes in the results $pvps = $results.SelectNodes('//PasswordViewPolicy') # Because the searchPasswordViewPolicy command returns all PVP's whose name contains the # search string, we need to select the exact match from the results and return just it's ID return ($pvps | Where Name -eq $pvpName).ID } # END getPvpId # Get the PVP IDs $oldPvpId = getPvpId($oldPVP) $newPvpId = getPvpId($newPVP) # Create a request body to grab a list of target accounts $request = @{ "adminUserID" = $CliCred.UserName "adminPassword" = $CliCred.GetNetworkCredential().Password "authentication" = "CSPM" "cmdName" = "searchTargetAccount" } write-host "Retrieving list of all target accounts..." # Make the API call and store the XML results [xml]$results = Invoke-WebRequest -Uri $Url -Body $request -Method Get # The actual results are stored as XML data in a cdata section of the parent xml [xml]$results = $results.'cw.appMessage'.content.'#cdata-section' # Create an array of target accounts that use the old PVP $toUpdate = $results.SelectNodes('//TargetAccount') | Where passwordViewPolicyID -eq $oldPvpId # Loop over the target accounts to update and change their PVP foreach($targetAccount in $toUpdate) { Write-Host "Updating target account $($targetAccount.ID) ($($targetAccount.userName))..." -NoNewline # Create a request body to update the target account $request = @{ "adminUserID" = $CliCred.UserName "adminPassword" = $CliCred.GetNetworkCredential().Password "authentication" = "CSPM" "cmdName" = "updateTargetAccount" "TargetAccount.ID" = $targetAccount.ID "TargetAccount.userName" = $targetAccount.userName "PasswordViewPolicy.ID" = $newPvpId } # Add the additional attributes back to the request (for some reason they are required for updateTargetAccount even if they don't change) ($targetAccount | select Attribute.*).psobject.properties | foreach {$request[$_.Name] = $_.Value} # Make the API call and store the XML results [xml]$results = Invoke-WebRequest -Uri $Url -Body $request -Method Get # Remove the password from the request data $request.adminPassword = "Removed for security" # Output completion message Write-Host $results.'cw.appMessage'.statusMessage # Write target account details to screen if ($results.'cw.appMessage'.statusMessage -ne "Success.") { Write-Host "FAILED Target account:" $targetAccount Write-Host "Request data:" $request } } Stop-Transcript