Import from CyberArk

Import Accounts from CyberArk Safes using Microsoft PowerShell and the CyberArk PACLI utility.

CyberArk includes a Command-Line Interface, PACLI, that communicates directly with the CyberArk Vault. It operates on "files" stored in "safes" in the vault. It can export CyberArk account data, which CyberArk clients like PrivateArk and Password Vault Web Access (PVWA) store as files in safes.

The instructions below use a PowerShell script that uses PACLI to export all the files matching a pattern. Using the default pattern "*," it exports all files from the Safe. It extracts the Username, Address, and password for each one; however, it can be configured to extract other fields if required. The script provides the exported files as objects, so ConvertTo-CSV is then used to transform them into a Comma-separated Value (CSV) format to import them into Keeper.

Prerequisites

Three external components are required to use the script below:

  1. CyberArk PACLI

  2. A Vault.ini configuration file

  3. A User.ini credential file

CyberArk PACLI

The PACLI is available for download from the CyberArk Marketplace website. It is a zip file containing the PACLI.exe binary and some supporting files. The script will expect the path of the directory containing the binary.

Vault.ini

The vault.ini file contains parameters PACLI needs to locate and log on to the vault. For example:

VAULT=CAMainVault
ADDRESS=10.11.12.13
PREAUTHSECUREDSESSION=YES
TRUSTSSC=YES

The VAULT can typically be left as "CAMainVault."

The ADDRESS is the hostname or IP address of the CyberArk Vault server.

The PREAUTHSECUREDSESSION and TRUSTSSC settings are required when the log-on user is authenticated via LDAP (Active Directory) or RADIUS. Otherwise, they may be omitted.

User.ini

The User.ini file is in INI format. However, it is generated using theCreateCredFile.exe tool that CyberArk includes, along with some of its components. For example, generating a user.ini for Myuser in the CORP Active Directory domain:

CreateCredFile.exe User.ini Password /Username Myuser /Password "MyPassw0rd!" /ExternalAuth /OSUsername CORP\Myusername

The latest version of the PACLI zip contains the tool. Running it with the /? parameter will explain the other options that are useful in other authentication scenarios.

Export

Paste the following into a file ending with .ps1, e.g., Export-CyberArkSafeFiles.ps1

<#
.SYNOPSIS
Exports 'files', i.e., CyberArk Account passwords from a CyberArk Safe using PACLI.

.DESCRIPTION
Uses CyberArk's PACLI command to export files from a CyberArk Safe.
It retrieves files, their categories, and contents and exports an object for each.
It uses filepattern=* to get all files in the safe by default.
The default categories are 'Address' and 'UserName'.
#>
param (
    # The name of the 'Vault' in CyberArk, e.g., 'CAMainVault'
    [Parameter(Mandatory = $true)][string]$VaultName,
    # The name of the 'Safe' in CyberArk
    [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][string]$SafeName,
    # The CyberArk log on user (must match credentials in the User.ini)
    [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][string]$Username,
    # The path to the PACLI directory containing PACLI.exe
    [Parameter(Mandatory = $true)]
    [ValidateScript({ Test-Path -PathType Leaf (Join-Path $_ 'PACLI.exe') })]
    [string]$PACLIPath,
    # Arguments `findfiles` uses to generate the list of files to export
    [string[]]$FindFilesArguments = 'filepattern=*',
    # The categories to export from the files
    [Parameter()][string[]]$Categories = @('Address', 'UserName'),
    # A CyberArk Vault.ini file
    [Parameter()][ValidateScript({ Test-Path $_ -PathType Leaf })]
    [string]$VaultIniPath = 'Vault.ini',
    # A CyberArk User.ini (or .cred) file as generated by CreateCredFile.exe
    [Parameter()][ValidateScript({ Test-Path $_ -PathType Leaf })]
    [string]$UserIniPath = 'User.ini',
    # The folder in the safe to export files from--most use 'Root'
    [string]$FolderName = 'Root',
    # The session ID to use for the underlying PACLI commands
    [Parameter()][ValidateNotNullOrEmpty()][string]$SessionId,
    # ErrorAction for retrievefile errors
    [Parameter()][ValidateSet('Stop', 'Continue', 'SilentlyContinue')]
    [string]$PACLIErrorAction = 'Continue'
)

$PACLI = Join-Path $PACLIPath 'PACLI.exe' -Resolve

function Invoke-PACLI {
    param (
        [Parameter(Mandatory = $True)][string]$Command,
        [Parameter(ValueFromRemainingArguments)][string[]]$Arguments
    )
    $Executable = ".\{0}" -f (Split-Path -Leaf $PACLI)
    $CommandLine = "$Executable $Command $($Arguments -join ' ')"
    try {
        Push-Location $(Split-Path -Parent $PACLI) -StackName 'PACLI'
        $Output = (& $Executable $Command $Arguments 2>$null)
        if ($LastExitCode -eq 0) {
            $Output
        }
        else {
            switch ($PACLIErrorAction) {
                'Continue' {
                    Write-Error "'$CommandLine' exited with code $LastExitCode"
                }
                'Stop' { throw "'$CommandLine' exited with code $LastExitCode" }
            }
        }
    }
    finally {
        Pop-Location -StackName 'PACLI'
    }
}

Invoke-PACLI init

$PACLIDefaults = "vault=$VaultName", "user=$Username", "safe=$SafeName", 
"folder=$FolderName"
if ($SessionId) {
    $PACLIDefaults += "sessionId=$SessionId"
}
Invoke-PACLI default @PACLIDefaults
Invoke-PACLI definefromfile vault=$VaultName parmfile=(Resolve-Path $VaultIniPath) |
Out-Null
Invoke-PACLI logon logonfile=(Resolve-Path $UserIniPath) | Out-Null
Invoke-PACLI opensafe | Out-Null

try {
    # Create a temporary file to store the file contents during processing
    $tempFile = [IO.Path]::GetTempFileName()
    # Split the tempFile path into the folder and the filename for 'retrievefile'
    $localFolder = Split-Path $tempFile
    $localFile = Split-Path -Leaf $tempFile

    # Get the list of files in the safe
    Invoke-PACLI findfiles $FindFilesArguments 'output(name)' |
    Where-Object { $_.Trim() -ne '' } |
    ForEach-Object {
        $file = @{ Name = $_ }
        # Retrieve the file and store the contents (the password) in the file object
        Invoke-PACLI retrievefile file=$_ localfolder=$localFolder localfile=$localFile
        if ($LastExitCode -ne 0) { return }
        $file.Password = (Get-Content $tempFile).TrimEnd([Char]0) # Can be null-padded
        # Get the list of categories for the file as a quoted CSV string
        Invoke-PACLI listfilecategories file=$_ 'output(all,enclose)' |
        ForEach-Object {
            # Get the category name and value and strip the quotes
            $category = ($_ -split ',' | ForEach-Object { $_.Trim('"') })[0..1]
            # Add the category to the file object if it is on the list
            if ($category[0] -in $Categories) {
                $file[$category[0]] = $category[1]
            }
        }
        [PSCustomObject]$file
    }
}
finally {
    Remove-Item -Path $tempFile -Force
}

Invoke-PACLI closesafe vault=$VaultName user=$Username safe=$SafeName | Out-Null
Invoke-PACLI logoff vault=$VaultName user=$Username | Out-Null
Invoke-PACLI term | Out-Null

Extract the PACLI.zip into the same directory or a sub-directory of the directory containing the script.

Open PowerShell and change to the directory containing the script.

Run the script and pipe the output into Export-CSV:

.\Export-CyberArkSafeFiles.ps1 CAMainVault MySafe Myuser .\PACLI-Rls-v11.5.3 |
Export-CSV Records.csv -Delimiter "`t" -Encoding utf8 -NoHeader -UseQuotes Never

Note the use of use of tab characters instead of commas, the use of UTF-8 encoding, excluding a header and not quoting the data all help Keeper import the data properly.

Transformation

PowerShell can help transform the data beyond just formatting it as CSV. This more advanced example creates the "login" field by combining the Username and Address fields and uses it as the "title" field as well.

.\Export-CyberArkSafeFiles.ps1 CAMainVault MySafe Myuser .\PACLI-Rls-v11.5.3 |
Select-Object @{l='Folder';e={$_.Name -replace "-$($_.Address)-$($_.Username)", '' }},
 @{l='Login';e={'{0}@{1}' -f $_.Username, $_.Address}}, Password |
Select-Object Folder, @{l='Title';e={$_.Login}}, Login, Password |
Export-Csv Records.csv -Delimiter "`t" -Encoding utf8 -NoHeader -UseQuotes Never

Import

Follow the instructions to Import a CSV Text File.

Last updated