Custom Powershell to Update File Dependencies with Service Account passwords

Overview

I was recently asked if you can use NPS to update various configuration files that have passwords embedded in them. Typically, you’ll see this with various applications that store service account passwords.
In order to do this, you can create an Activity that will run a custom PowerShell step and connect to the target resource and run commands using the Service Account for that resource.
This functionality allows you to extend NPS to do things that you can’t do with the built-in Actions for Activities.

Description

The First thing you’ll need to do is create a vault connector back to NPS “BYOV (Bring Your Own Vault)”, the reason behind this is because the default behavior for an Activity is to ‘enable/disable’ the account so if you were to use the default ‘managed’ account method your service account would be in a disabled state when the activity completes. Using BYOV, NPS will avoid that scenario. Find instructions on configuring NPS as a vault connector here: Creating a Custom BYOV Connector to Check out Service Accounts from Privilege Secure

Next create or update an Activity, adding a new Run Custom PowerShell step.

When you create a new Run Custom PowerShell step, it pre-populates with an example. You can just use CTRL-A and then press Delete to remove the example.

Note that you will need to modify the script to meet the requirements for your environment, for example:

The xml file location/name (i.e. c:\temp\sample xml.xml)

The xml file structure, in the example below we are parsing for a node in the XML that is labeled ‘password’ and updating that node with the new password

In the (now empty) PowerShell editor for your Activity, paste the following:

$targetHost = Get-SbPAMHost -Id $HostId

$session = New-SbPAMPSSession -RemoteHost $targetHost -Credential (Get-PSCredential -Credentials $Credentials)

if ($null -ne $session) {

try

{

Add-SbPAMActionLog -Type Info -Message "Connecting to $($targetHost.DnsHostName)"

$output = Invoke-Command -Session $Session -ScriptBlock {

# all pipeline results are sent back

# NOTE you don't have the SBPAM module on the remote

# AND you won't have API access here either

#Load the file

$xmldoc = [xml](Get-Content 'C:\Temp\Sample XML.xml')

# Define the path to the XML file

$xmlFilePath = 'C:\Temp\Sample XML.xml'

#locate the password node in the XML file

$item = $xmldoc.SelectSingleNode('//Password')

#update the node with the current service account password

$item.InnerText = $using:UserCredentials.password

# Save the updated XML content to the same file

$xmldoc.Save($xmlFilePath)

}

$output | foreach-object {

# Use a prefix for the message to avoid sending empty strings (PowerShell doesn't like null or empty string args)

Add-SbPAMActionLog -Message "Result: $_" -Type Info

}

}

finally

{

# Close the session

Remove-PSSession -Session $session

}

}

Here is a screenshot of an example activity:

Activity Type = task automation

Login Account Template = the absolute name of the service account you’re looking to retrieve the password for

Vault Connector = The BYOV connection explained earlier

Session (Connect) = is where I chose to run the custom powershell script.

When the Activity runs, NPS will update the file(s) specified in the script(s) with the current service account password. This would be something you could run AFTER you’ve gone through the Service Account rotation process for discovered Windows Services and Scheduled tasks: Account Dependencies Window. The scripting process allows you to further extend NPS’ functionality.

PS – It’s highly recommended that you configure NPS to use WinRM over HTTPS to ensure that the password stays encrypted over the wire. This can be configured in the ‘Global Settings’ page: Global Settings Page

Additional resources:

17 Likes

Here is an add-on sample for replacing the password in a SQL Connection string.

 
$targetHost = Get-SbPAMHost -Id $HostId
$session = New-SbPAMPSSession -RemoteHost $targetHost -Credential (Get-PSCredential -Credentials $Credentials)
if ($null -ne $session) {
    try
    {
        Add-SbPAMActionLog -Type Info -Message "Connecting to $($targetHost.DnsHostName)"
       
        $output = Invoke-Command -Session $Session -ScriptBlock {
            # all pipeline results are sent back
            # NOTE you don't have the SBPAM module on the remote
            # AND you won't have API access here either
            #Load the file

# # Sample Script to replace a password in a SQL Connection String File with a value stored in Netwrix Privilege Secure for the target service account.
# Define variables
$FilePath = 'c:\Temp\Sample SQL.sql' # Update this path
$newPassword = $using:UserCredentials.password     # The new password to set

# Function to replace password in connection string
function Update-SqlConfigPassword {
    param(
        [string]$FilePath,
        [string]$NewPassword
    )
    
    try {
        # Read the content of the configuration file
        $content = Get-Content -Path $FilePath -Raw
        
        # Display original content - used for troubleshooting outside of NPS
        #Write-Host "Original Configuration:" -ForegroundColor Yellow
        #Write-Host $content
        #Write-Host "`n"
        
        # Regular expression pattern to match Password field
        # This pattern captures everything between "Password=" and the next ";" or end of string
        $pattern = '(Password=)([^;]+)(;|$)'
        
        # Replace the password using regex
        $newContent = $content -replace $pattern, "`${1}$NewPassword`${3}"
        
        # Alternative more specific pattern if you need exact matching
        # $pattern = '(?<=Password=)[^;]+'
        # $newContent = $content -replace $pattern, $NewPassword
        
        # Display new content - used for troubleshooting outside of NPS
        #Write-Host "Updated Configuration:" -ForegroundColor Green
        #Write-Host $newContent
        #Write-Host "`n"
        
        # Write the updated content back to the file
        Set-Content -Path $FilePath -Value $newContent -Force
        
               
        # Return the updated content
        #return $newContent
    }
    catch {
        Write-Host "Error updating password: $_" -ForegroundColor Red
        return $null
    }
}

#Call the function and password variables to the function
Update-SqlConfigPassword $FilePath $newPassword
 
        }
        $output | foreach-object {
            # Use a prefix for the message to avoid sending empty strings (PowerShell doesn't like null or empty string args)
             
            Add-SbPAMActionLog -Message "Result: $_" -Type Info
        }
    }
    finally
    {
        # Close the session
        Remove-PSSession -Session $session
    }
}

You can combine these actions in a single activity in the case where the service account password might be referenced in various file types on a given host(s).

2 Likes

Here is an add-on sample for replacing the password in an Oracle Connection string.

 
$targetHost = Get-SbPAMHost -Id $HostId
$session = New-SbPAMPSSession -RemoteHost $targetHost -Credential (Get-PSCredential -Credentials $Credentials)
if ($null -ne $session) {
    try
    {
        Add-SbPAMActionLog -Type Info -Message "Connecting to $($targetHost.DnsHostName)"
       
        $output = Invoke-Command -Session $Session -ScriptBlock {
            # all pipeline results are sent back
            # NOTE you don't have the SBPAM module on the remote
            # AND you won't have API access here either
            #Load the file

# Sample Script to replace a password in an Oracle Connection String File with a value stored in Netwrix Privilege Secure for the target service account.
# Define variables
$FilePath = 'c:\Temp\Sample Oracle.ora' # Update this path
$newPassword = $using:UserCredentials.password     # The new password to set

# Function to replace password in connection string
function Update-OracleConfigPassword {
    param(
        [string]$FilePath,
        [string]$NewPassword
    )
    
    try {
        # Read the content of the configuration file
        $content = Get-Content -Path $FilePath -Raw
        
        # Display original content - used for troubleshooting outside of NPS
        #Write-Host "Original Configuration:" -ForegroundColor Yellow
        #Write-Host $content
        #Write-Host "`n"
        
       # Regular expression pattern to match Password field
       # This pattern captures everything between "Password=" and the next ";" or end of string
       $pattern = '(Password\s*=\s*)([^;]+)(;|$)'
        
        # Replace the password using regex
        $newContent = $content -replace $pattern, "`${1}$NewPassword`${3}"
             
        # Display new content - used for troubleshooting outside of NPS
        #Write-Host "Updated Configuration:" -ForegroundColor Green
        #Write-Host $newContent
        #Write-Host "`n"
        
        # Write the updated content back to the file
        Set-Content -Path $FilePath -Value $newContent -Force
        
        # Write-Host "Password successfully updated in the configuration file!" -ForegroundColor Green
        
        # Return the updated content - used for troubleshooting outside of NPS
        #return $newContent
    }
    catch {
        Write-Host "Error updating password: $_" -ForegroundColor Red
        return $null
    }
}

Update-OracleConfigPassword $FilePath $newPassword
 
        }
        $output | foreach-object {
            # Use a prefix for the message to avoid sending empty strings (PowerShell doesn't like null or empty string args)
             
            Add-SbPAMActionLog -Message "Result: $_" -Type Info
        }
    }
    finally
    {
        # Close the session
        Remove-PSSession -Session $session
    }
}
1 Like