Alright, let's get this over with. Another quarter, another SOX audit breathing down our necks. The auditors wanted a report on every single privileged account change from the last three months, with specific fields, formatted just so, and delivered on a recurring schedule. Delinea's canned reports? Not even close. The interface for building them feels like it was designed by someone who's never actually had to *use* a report under deadline.
So I had to roll my own. The goal: automate a SOX-compliant report of all privileged account creations, modifications, and deletions, output to CSV, and emailed to the compliance team every Friday. No manual clicks, no excuses.
Here's the core of it, using Delinea's PowerShell PAM SDK. You'll need the modules installed and appropriate permissions. The trick is in the filters and the property selection—auditors love specific timestamps and actor information, which the default exports often bury.
```powershell
# Connect to your Delinea server
$session = New-PASSession -BaseURI https://your-vault.url -Credential $secureCreds
# Build a date filter for the last 90 days
$startDate = (Get-Date).AddDays(-90).ToString("yyyy-MM-ddTHH:mm:ss")
$filter = "timeStamp gt $startDate"
# Fetch the events. We need Account Created, Account Deleted, Account Properties Changed.
# Event IDs are key here; you have to dig through the enum or documentation.
$events = Get-PASEvent -eventType Account -filter $filter -sessionToken $session.Token | Where-Object { $_.id -in @(1001, 1003, 1004) }
# Parse and format the output. The raw object is a mess.
$reportData = foreach ($event in $events) {
[PSCustomObject]@{
Timestamp_UTC = $event.timeStamp
Event_Type = $event.eventName
Target_Account = $event.targetUser
Acting_User = $event.authUser
Safe_Name = $event.safeName
Details = $event.details
Source_IP = $event.ipAddress
Event_ID = $event.id
}
}
# Export to CSV with a date-stamped filename
$filename = "SOX_Privileged_Access_Report_$(Get-Date -Format 'yyyyMMdd').csv"
$reportData | Export-Csv -Path $filename -NoTypeInformation
# Disconnect the session
Close-PASSession -sessionToken $session.Token
```
You wrap this in a scheduled task on a trusted jumpbox. Do NOT run this from some random workstation. The real headaches were:
* **Event ID inconsistencies:** Some "properties changed" events are logged under different IDs for different object types. You have to test and verify.
* **API paging:** If you have a lot of events, you need to implement paging with `-nextLink`. My snippet above is the simple version. For a real production script, you're looping.
* **Detail field parsing:** The `details` field is a JSON blob. If you need something specific from it (like *which* property changed), you have to parse it further, adding another transformation step.
Is it elegant? No. But it's automated, repeatable, and passes audit. That's more than I can say for the out-of-the-box reporting dashboard, which seems to be designed primarily for generating colorful, useless PDFs.
fix the pipe
Speed up your build