All pages
Powered by GitBook
1 of 4

Post-Rotation Scripts

Perform privileged automation tasks with Post-Rotation scripts and password rotation

Overview

Post-rotation scripts (PAM Scripts) are user-defined software programs that can perform privilege automation tasks. Scripts can be attached to any PAM resource records in the vault. Depending on the PAM record the script is attached to, the script will execute either on the Keeper Gateway, or the remote host where password rotation occurred.

The following table shows all the available PAM Records and where the attached script will execute:

Record Type
Attached Post Execution Script will execute on

PAM Configuration

Gateway

PAM Machine

The Machine specified in the record

PAM Database

Gateway

PAM Directory

Gateway

PAM User

Gateway

Rotation Options on PAM User Records

When setting up rotation on a record on a PAM User record, you can select from one of the following methods:

  • General

  • IAM User

  • Run PAM scripts only

When the "General" or "IAM User" methods are selected, Keeper will attempt to rotate the credentials using built-in capabilities based on the information stored in the record.

When the "Run PAM scripts only" option is selected, Keeper will skip the default rotation task and immediately run the attached PAM scripts on the gateway.

Order of Execution

Scripts will be executed in the following order:

  1. Scripts attached on PAM User records

  2. Scripts attached on PAM Machine, PAM Database, or PAM Directory Record types

  3. Scripts attached on PAM Configuration Record types

If multiple scripts are attached to a record, scripts will be executed in the order they appear on the PAM Record.

Common Use Cases

Here are some of the use cases made possible with Keeper Post-Rotation Scripts:

  • Custom rotation scripts for any type of target

  • Revoking access to a resource

  • Sending notifications to team members

  • Propagating the password change to other systems

  • Any other custom privilege automation task

Documentation included

  • Inputs and outputs

  • Attaching scripts

  • Code Examples

Inputs and Outputs

Description of the input parameters passed into PAM Scripts

Overview

Upon successful rotation of credentials on a PAM record, Keeper executes the attached Post-Rotation scripts with parameters containing information on the involved records, credentials, and user.

Inputs

The Keeper Gateway executes PAM scripts and provides inputs to the script through stdin parameters. These parameters are placed in a Base64 encoded JSON object and piped to the script.

For example, the Keeper Gateway will essentially execute the script on a Linux machine as follows:

history -c && echo "BASE64==......" | /path/to/script.sh

Windows:

"BASE64==......" | .\script.ps1; Clear-History

The following keys can be found in this base64 encoded JSON object:

Key
Description

providerRecordUid

The UID of the PAM Configuration record

resourceRecordUid

The UID of the PAM Resource record

userRecordUid

The UID of the PAM User record

newPassword

The new password generated for the User

oldPassword

The previous password for the User

user

The username for the User

records

Base64-encoded JSON array of record dictionaries

Additional Info on records field

The records key value is a Base64, JSON array of dictionaries. This array will include the following data:

  • PAM Configuration information

  • Related PAM Machine, PAM Database, or PAM Directory Record Data

  • Additional Records supplied when uploading the post-rotation scripts

  • User Record Data

Each dictionary object will contain:

  • uid - The UID of the Vault record.

  • title - The title of the Vault record.

  • The rest of the dictionary will contain key/value pairs of the record's data where the key will be the label of the field. If the field does not contain a label, the field type will be used. If the key already exists, a number will be added to the key.

Outputs

Upon execution of the PAM Script, an array is returned containing instances of RotationResult for each script that was executed. The class RotationResult has the following attributes:

  • uid - Keeper Vault record UID that has the script attached

  • command - Command that was issued to the shell

  • system - Operating system the script will run upon

  • title - Title of the script attached to the Keeper Vault record

  • name - Name of the script attached to the Keeper Vault record

  • success - Was the script successful?

    • Linux and macOS - Script returned in a 0 return code.

    • Windows - Script returned a True status.

  • stdout - The stdout from the execution of the script

  • stderr - The stderr from the execution of the script

Additionally, the following methods can be used to determine if the script was a success, or not:

Method
Descripton

was_failure

boolean, return True if failure, False if success

was_success

boolean, returns True if success, False if failure

With this, it is possible to customize logging:

Example in Python
for r in results:
    if r.was_failure:
        print(f"For record {r.uid}, the script {r.title} failed: {r.stderr}")

Troubleshooting

The class RotationResult has attribute stderr which logs the errors from execution of the script.

Although post rotation script results and information are available via the RotationResult class, errors and outputs of scripts are based on the type of shell the script is executed on. Keeper does not check the stdout or errors of the scripts as Keeper does not know what defines as an error for a customer-controlled script.

For example, if a BASH script does not contain a set -e, the script will continue even if part of the script fails. If the script exits with a 0 return code, the script will be flagged as successful.

Therefore, it is up to the customer to properly handle the outputs and errors of the script.

Attaching Scripts

Attaching post-rotation scripts to PAM resource records

Attaching Post Rotation Scripts

When creating or editing a PAM record, click on the Add PAM Script button

Clicking on Add PAM Script will allow you to:

  • Browse locally and choose your Rotation Script(s).

  • Add "Additional Credentials". This is an option to add additional records which contains the credentials needed by the post rotation script. These credentials must be available to the Keeper Gateway.

  • Specify an optional custom command to executed. In the below screenshot, a python script (postRotationTest.py) is attached, and a specific command to be used to execute the python script.

After successfully selecting the script(s), the record will be updated to show the attached Post Rotation scripts:

Click Save to create or update the record. Attached Post Rotation Scripts can be deleted or edited by clicking on their respective actions.

Code Examples

Examples of post-rotation scripts in KeeperPAM

Echo Inputs

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.

  • Bash

  • PowerShell

  • Keeper Secrets Manager SDKs

Bash

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