The below example post-rotation scripts simply echo the input parameters in various languages and platforms. The output of the print statements can be found in the Keeper Gateway log file.
Note: For this example, jq needs to be installed to parse the JSON. Attach this as a PAM script and perform the rotation. The Gateway logfile will contain the output.
decode-and-echo.sh
#!/bin/bash
# Read the Base64 encoded JSON input and decode it
decoded_json=$(cat | base64 --decode)
# Extract the "records" field, which is Base64 encoded, and decode it separately
records_base64=$(echo "$decoded_json" | jq -r '.records')
# Decode the Base64 "records" field and pretty-print the JSON
decoded_records=$(echo "$records_base64" | base64 --decode | jq '.')
# Print the entire decoded JSON, replacing "records" with the decoded version
echo "$decoded_json" | jq --argjson records "$decoded_records" '.records = $records'
PowerShell
Attach this as a PAM script and perform the rotation. The Keeper Gateway logfile will contain the output. This script simply echoes the input.
Begin {
# Executes once before first item in pipeline is processed
}
Process {
# Stop if error. If not set, result value will be True and assumed there
# was no problem.
$ErrorActionPreference = "Stop"
# Executes once for each pipeline object
$JSON = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($_))
$Params = ($JSON | ConvertFrom-Json)
Write-Output "providerRecordUid=$($Params.providerRecordUid)"
Write-Output "resourceRecordUid=$($Params.resourceRecordUid)"
Write-Output "userRecordUid=$($Params.userRecordUid)"
Write-Output "newPassword=$($Params.newPassword)"
Write-Output "oldPassword=$($Params.oldPassword)"
Write-Output "user=$($Params.user)"
$recordsJSON = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Params.records))
$records = ($recordsJSON | ConvertFrom-Json)
# Output full JSON for records
Write-Output "Full Records JSON: $recordsJSON"
# Extract the provider title from the records
$title = ($records | Where-Object {$_.uid -eq $Params.providerRecordUid}).title
Write-Output "Provider Title=$title"
# Loop through all records and display details
foreach ($record in $records) {
Write-Output "Record UID=$($record.uid)"
Write-Output "Record Title=$($record.title)"
Write-Output "Record Type=$($record.type)"
Write-Output "Record Details=$($record.details | ConvertTo-Json)"
}
}
End {
# Executes once after last pipeline object is processed
}
Here's a PowerShell script that sends a Webhook to a 3rd party site.
param (
[Parameter(ValueFromPipeline=$true)]
[string]
$Record
)
# Decode the Base64 input and convert it to a PowerShell object
$RecordJsonAsB64 = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Record))
$Params = $RecordJsonAsB64 | ConvertFrom-Json
# Prepare the webhook payload
$webhookPayload = @{
providerRecordUid=$Params.providerRecordUid
resourceRecordUid=$Params.resourceRecordUid
userRecordUid=$Params.userRecordUid
user=$Params.user
timestamp= (Get-Date).ToString("yyyy-MM-ddTHH:mm:ssZ")
message= "Post-rotation script executed successfully."
} | ConvertTo-Json
# Define the webhook URL
$webhookUrl = "https://webhook.site/3308ec5a-3fba-4e31-85ad-37b0f643ac82"
# Send the POST request to the webhook
try {
Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $webhookPayload -ContentType 'application/json'
Write-Host "Webhook message sent successfully."
}
catch {
Write-Error "Failed to send webhook message: $_"
}
Using Keeper Secrets Manager SDKs
The post rotation script is not limited to shell scripts. Applications can be written in languages like Python or C# to get the piped parameters. Since the UIDs of the Rotation involved records are passed in the params, the post-rotation script can use the Keeper Secrets Manager SDKs to get additional information.
#!/usr/bin/env python3
import sys
import base64
import json
from keeper_secrets_manager_core import SecretsManager
# sys.stdin is not an array, it can not subscripted (ie sys.stdin[0])
for base64_params in sys.stdin:
params = json.loads(base64.b64decode(base64_params).decode())
print(f"providerRecordUid={params.get('providerRecordUid')}")
print(f"resourceRecordUid={params.get('resourceRecordUid')}")
print(f"userRecordUid={params.get('userRecordUid')}")
print(f"newPassword={params.get('newPassword')}")
print(f"oldPassword={params.get('oldPassword')}")
print(f"user={params.get('user')}")
records = json.loads(base64.b64decode(params.get('records')).decode())
print("Provider Title="
f"{next((x for x in records if x['uid'] == params.get('providerRecordUid')), None).get('title')}")
ksm = SecretsManager(config=...)
resource_records = ksm.get_secrets(params.get('userRecordUid'))[0]
break