Create a New Dependency Changer for Synchronizing Passwords During RPC
In most environments, we recommend using a separate password for each account for optimal security. However in environments where identical credentials are used in multiple secrets, we recommend using RPC to change the password on one primary parent account secret, and then using a PowerShell dependency script to update values in child secrets. The PowerShell script calls back to Secret Server's API, retrieves a list of comma-separated values representing child secret IDs, and updates the values stored in the child secrets. We recommend using this process for no more than 25 child secrets.
Requirements
- A Secret Server instance version 10.1.000000 or newer with a premium add-on or Enterprise Plus
- A PowerShell implementation enabled and working properly. See Configuring WinRM for PowerShell
- the WellnessChecker tool
For this procedure you will need to create the four types of user accounts listed below, and for each account you will need to create a corresponding secret in Secret Server with the account's login credentials and other information.
Create the user accounts and secrets described below:
- An API User account and a corresponding secret. This API User account will NOT take up a user license. Recommended templates for the secret include the Active Directory template and the Web Password template. Credentials may be a local account or an Active Directory service account assigned to the Synchronization group, but must be stored in Secret Server to be passed to the PowerShell script.
- A primary parent account and a corresponding secret that has RPC set up and the PowerShell dependency script from this page attached. The primary parent account credentials may be either a local account or an Active Directory service account assigned to the Synchronization group.
- Child accounts with a corresponding secret for each account containing the child secret ID, with edit permissions granted to the API User account.
- A privileged Active Directory account and a corresponding secret that can run PowerShell on the Secret Server machine.
To create a new dependency changer for synchronizing passwords during RPC, follow the procedure below.
-
Download the WellnessChecker tool ZIP file.
-
Extract the ZIP file and run this command:
PowerShell.WellnessChecker.exe -fixerrors
-
In Secret Server, browse to Admin > Scripts.
-
Click the
symbol next to Create New.
-
In the New PowerShell Script dialog, fill in the fields for Name, Description, and Category.
-
In the Script field, paste in the script provided at the bottom of this page.
-
Click OK to save the file.
-
Browse to Admin > Configuration.
-
On the General tab, make sure Enable Webservices is set to Yes.
-
Browse to the primary parent account secret and ensure that RPC is setup on it.
-
In the primary parent account secret, click the RPC tab.
-
Click Edit.
-
In the secret grid at the bottom, select the API User account secret you created. The API User account secret should be the only secret in the grid.
-
Browse to Admin > Discovery and click the Configuration tab.
-
Click Discovery Configuration Options and select Extensible Discovery from the drop-down list.
-
On the Extensible Discovery Configuration page, click Configure Dependency Changers.
-
On the Secret Dependency Changers page, click Create New Dependency Changer.
-
In the New Dependency Changer dialog, click the Basic tab and enter the following information:
-
Click the Scripts tab and enter the following information:
-
In the Arguments field, paste the following:
$[1]$USERNAME $[1]$PASSWORD $PASSWORD $NOTES $[1]$DOMAIN
The actions of the Arguments are as follows:
-
$[1]$USERNAME
pulls the username from the privileged account on the primary parent account, which will be used to execute the PowerShell script. -
$[1]$PASSWORD
pulls the password from the associated secret on the primary parent account, which will be used to execute the PowerShell script. -
$PASSWORD
pulls the password from the primary parent account, which will be set for all secrets listed in the Notes field. -
$NOTES
pulls the Notes content from the primary parent account, and parses the comma separated list of secret IDs to find the other secrets to update. -
$[1]$DOMAIN
pulls the Domain field from the associated secret on the primary parent account. For local accounts, leave the Domain field on the associated secret empty. It must be listed last because of the way PowerShell parses empty fields.
-
-
Browse back to the Extensible Discovery Configuration page and this time, click Configure Dependency Templates.
-
On the Secret Dependency Templates Designer page, select the new dependency changer you configured in the last step.
-
Browse to the primary parent account secret and click the Dependencies tab.
-
Click New Dependency.
-
In the Create Dependency dialog, click the Select Type dropdown and select the PowerShell dependency template you created.
-
In the Edit Dependency dialog, enter
default
in the Machine Name field. -
Select a privileged account (active directory account secret able to run PowerShell on the server)
-
Add the following to the Arguments field:
$[1]$USERNAME $[1]$PASSWORD $PASSWORD $NOTES $[1]$DOMAIN
-
In the primary parent account secret's Notes field, ensure that the child secret IDs appear in a comma-separated-values list, for example
19,39,81...
Now the dependency has been added and you can test the full process by running a remote password change on the primary parent account. All of the secrets listed by ID in the Notes field should be updated with the same password.
PowerShell Script
Replace $url
with the name of the machine hosting your Secret Server instance.
$url = 'http://MySecretServerURL/webservices/sswebservice.asmx';
$username = $Args[0]
$password = $Args[1]
$newpassword = $Args[2]
$secretIdArray = $Args[3]
$domain = $Args[4]
$proxy = New-WebServiceProxy -uri $url -UseDefaultCredential
$result1 = $proxy.Authenticate($username, $password, '', $domain)
if ($result1.Errors.length -gt 0){
$errors = $result1.Errors[0]
Write-Debug "Errors result1: $errors"
exit
} else {
$token = $result1.Token
}
$secretIds = $secretIdArray -split ","
foreach($secretId in $secretIds){
$result2 = $proxy.GetSecret($token, $secretId, $false, $null)
if ($result2.Errors.length -gt 0){
$errors = $result2.Errors[0]
Write-Debug "Errors result2: $errors"
} else {
$secretName = $result2.Secret.Name
Write-Debug "Updating Secret: $secretName"
foreach ($item in $result2.Secret.Items) {
if($item.IsPassword) {
$item.Value = $newpassword
}
}
$secret = $result2.Secret
$result3 = $proxy.UpdateSecret($token, $secret)
if ($result3.Errors.length -gt 0) {
$errors = $result3.Errors[0]
Write-Debug "Errors result3: $errors"
} else {
Write-Debug "Updated Secret: $secretName"
}
}
}