Zu Content springen
Deutsch
  • Es gibt keine Vorschläge, da das Suchfeld leer ist.

Automatischer Export in csv Files

Hier finden Sie ein PowerShell Skript zum Export der Daten.

Generell empfehlen wir die eingebaute Backup-Lösung zu verwenden. Diese erzeugt eine Datei welche hochverschlüsselt ist (AES256). Dieses Backup kann auch an einem Einzelplatz / Notfallnotebook oder ähnlichem in den Pleasant Password Server eingespielt werden.


Tipp:
Über den KeePass Client können Sie in den Formaten csv, html, xml und kdbx exportieren. Gerade der Export im Format xml ist sehr mächtig, da er alle Felder exportiert. 

 
Wenn Sie dennoch eine .csv File mit den Daten erzeugen wollen, finden Sie hier ein PowerShell-Beispiel, dass Sie sich entsprechend anpassen können.
 

Achtung:

Die Erstellung von Skripten und die Interaktion mit der API liegt in Ihrer Verantwortung. Das bereitgestellte Skript ist als Beispiel gedacht und sollte an Ihre individuellen Anforderungen angepasst werden. Bitte denken Sie daran, dass die Anpassung und Nutzung des Skripts auf eigenes Risiko erfolgt und wir leider keinen Support dafür anbieten können.

 
# Create a CSV file of all credential entries in 

# Pleasant Keepass Server including:

#   - passwords, foldername, folder path, 

#   - tags, totp secret, 

#   - file attachments, and 

#   - password breach potential indicator.

#

# Version: 

#  - 3.3.3

#

# Functionality:

#  - Export Password Server entries

#  - Download and save any attachment files separately

#  - Anonymously check passwords and hashes against the popular haveibeenpwned.com database

#

# Usage:

#  - enter your parameter values 

#  - to integrate with password breach checking, first install PwnedPassCheck (below)

#  - running the script will prompt for username/password login 

#

# Parameter Options:

#    password server url,

#    export path,

#    export passwords,

#    export all results,

#    check for pwned password,

#    rate-limit password retrievals

#

#

# Pwned Module Integration & Usage:

#  - PwnedPassCheck (v2.0) - GitHub: PowerShell haveibeenpwned integration module, by rmbolger

#     https://github.com/rmbolger/PwnedPassCheck

#  - To use this module, first install by following the instructions or use this command:

#     Install-Module -Name PwnedPassCheck -Scope CurrentUser






$PasswordServerURL = "https://mydomain:10001"  # The URL for your Password Server 

$ExportPath = 'c:\Temp\ExportedEntries.csv'    # Where to write exported entry list

$AttachmentsPath = 'c:\Temp\Attachments'       # Where to save attachments

$ExportPasswords = $true                       # Include passwords in export? (many hits to db)

$DelayTime = .05                               # Rate-limit password retrievals (in secs)

$ExportAll = $true                             # (true) Export all credentials, or (false) just exports 1 sample record

$ExportAttachments = $true                     # Export attachments

$ExportCustomFields = $true                    # Export custom user fields

$ExportCustomAppFields = $true                 # Export custom application fields

$CheckPwned = $false                           # Check if password has been pwned?




$Results = @()         # Our entries (final result)

$FolderLookup = @{}    # Hash-table folder lookup

$ThisLevelCreds = @()  # Entry list




# Prompt for admin credentials to access Password Server

$Cred = Get-Credential 




# Create the OAuth2 token params

$tokenParams = @{

  grant_type='password';

  username=$Cred.UserName;

  password=$Cred.GetNetworkCredential().password;

}




# Authenticate to Pleasant Password Server 

try {

    $JSON = Invoke-WebRequest -Uri "$PasswordServerURL/OAuth2/Token" -Method POST -Body $tokenParams -ContentType "application/x-www-form-urlencoded" -ErrorAction stop

    $Token = (ConvertFrom-Json $JSON.Content).access_token

    Write-Host "Logs: Authentication successful"

} catch {

    Write-Error "Logs: Failed to authenticate: $_"

    exit

}




# Prep JSON headers

$headers = @{

  "Accept" = "application/json"

  "Authorization" = "$Token"

}




# Ensure the attachments folder exists

if ($ExportAttachments -and -not (Test-Path -Path $AttachmentsPath)) {

    New-Item -Path $AttachmentsPath -ItemType Directory

    Write-Host "Logs: Created attachments folder at $AttachmentsPath"

}




# Function to get all attachments from an entry

function Get-Attachments {

    param (

        [string]$EntryId,

        [string]$BaseUrl,

        [string]$ApiKey

    )




    $url = "$BaseUrl/api/v5/rest/entries/$EntryId/attachments"




    $headers = @{

        "Authorization" = "Bearer $ApiKey"

    }




    try {

        $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get

        #Write-Host "Logs: Retrieved attachments for EntryId ${EntryId}"

        return $response

    } catch {

        Write-Error "Logs: Failed to retrieve attachments for EntryId ${EntryId}: $_"

        return $null

    }

}




# Function to save an attachment to a file

function Save-AttachmentToFile {

    param (

        [string]$FileName,

        [string]$FileData,

        [string]$OutputPath

    )




    $bytes = [System.Convert]::FromBase64String($FileData)

    $filePath = Join-Path -Path $OutputPath -ChildPath $FileName




    try {

        [System.IO.File]::WriteAllBytes($filePath, $bytes)

        Write-Host "Logs: Saved attachment to $filePath"

    } catch {

        Write-Error "Logs: Failed to save attachment to ${filePath}: $_"

    }

}







# Function to get all folders and credentials

function Get-AllFoldersAndCredentials {

    param (

        [string]$BaseUrl,

        [hashtable]$Headers

    )




    try {

        $KeepassData = Invoke-RestMethod -method get -Uri "$BaseUrl/api/v5/rest/folders" -Headers $Headers -ContentType 'application/json'

        Write-Host "Logs: Retrieved folders and credentials"

        return $KeepassData

    } catch {

        Write-Error "Logs: Failed to retrieve folders and credentials: $_"

        exit

    }

}







# Retrieve all folders and credentials

$KeepassData = Get-AllFoldersAndCredentials -BaseUrl $PasswordServerURL -Headers $headers




# Make the command a variable so we can execute the .property syntax to access the child properties using invoke-expression 

$global:Command = '($KeepassData)'




# Function to get the full path of a folder

function Get-FolderPath {

    param (

        [string]$folderId,

        [hashtable]$folderLookup

    )




    $folderPath = "\"

    while ($folderId -ne "00000000-0000-0000-0000-000000000000") {

        $folder = $folderLookup[$folderId]

        $folderPath = $folder[0] + "\" + $folderPath

        $folderId = $folderLookup[$folderId][1]   # recurse on the parent group id

    }




    return $folderPath.TrimEnd("\")

}




$EntryCount = 0

$path = ""




# Will break once all of the levels have been processed

:outerLoop while(1 -eq 1)

{

    # Retrieve the folders at the current level

    $ThisLevelFolders = $null

    $ThisLevelFolders = Invoke-Expression -Command $global:Command




    ForEach($folder in $ThisLevelFolders | select name, id, parentid, notes) 

    { 

        $FolderLookup += @{ $folder.id = $folder.name, $folder.parentid, $folder.notes }

    }




    # Retrieve the entries in these folders




    $global:Command = "$global:Command."+"children"




    $ThisLevelCreds = $ThisLevelFolders.credentials




    ForEach($row in $ThisLevelCreds)

    {




if ($ExportPasswords)

{

$pwd = (Invoke-WebRequest -Uri "$PasswordServerURL/api/v5/rest/credential/$($row.id)/password" -Headers $headers -Method Get).Content.Trim([char]0x022)

}

else {$pwd = ""}

 

if ($CheckPwned)

{

$pwned = (Get-PwnedPassword $pwd).SeenCount

}

else {$pwned = ""}




        # Get the folder name and full path

        $groupName = $folderLookup[$row.GroupId][0]

        $path = Get-FolderPath -folderId $row.GroupId -folderLookup $FolderLookup




        # Retrieve attachments

        $attachmentFileNames = @()

        $attachmentFileData = @()

        $attachmentFileSizes = @()




        if ($ExportAttachments) {

            if ($attachments) {

                foreach ($attachment in $attachments) {

                    Write-Host "Logs: Attachment found for EntryId $($row.id), saving to file..."

                    Save-AttachmentToFile -FileName $attachment.FileName -FileData $attachment.FileData -OutputPath $AttachmentsPath

                    $attachmentFileNames += $attachment.FileName

                    $attachmentFileData += $attachment.FileData

                    $attachmentFileSizes += $attachment.FileSize

                }

            } else {

                #Write-Host "Logs: No attachments found for EntryId $($row.id)"

            }

        }

        




        # Retrieve custom fields if available

        $customUserFields = if ($ExportCustomFields) { $row.CustomUserFields } else { @{} }

        $customAppFields = if ($ExportCustomAppFields) { $row.CustomApplicationFields } else { @{} }




        # Set the entry fields

        $Results +=[pscustomobject]@{

                Path = $path

                GroupName = $groupName

                GroupId = $row.GroupId 

                Id = $row.id

                Name = $row.name

                URL = $row.url

                Username = $row.username

                Tags = ($row.tags.name) -join " ; "

                Created = $row.created

                Modified = $row.modified

                Expires = $row.expires

                Notes = $row.notes

                TOTPIssuer = $row.issuer

                TOTPSecret = $row.secret

                TOTPDigits = $row.digits

                TOTPPeriod = $row.period

Password = $pwd

Pwned = $pwned

                AttachmentFileNames = $attachmentFileNames -join ", "

                AttachmentFileData = $attachmentFileData -join ", "

                AttachmentFileSizes = $attachmentFileSizes -join ", "

                CustomUserFields = $customUserFields

                CustomApplicationFields = $customAppFields

        }




        $EntryCount += 1




# Count 

    if(-not $ExportAll)

        {break outerLoop}

        

    # Add a delay here. The parameter is in seconds.

        Start-Sleep -Seconds $DelayTime

    }

 

    # If no more data is found in the current level, assume we've hit the end and exit.  Otherwise append .children to dig another level deeper

    if($ThisLevelFolders.count -eq 0) 

    {break}

}







If ($ExportAll -eq $true)

{

# Export to CSV file

$Results | Export-CSV $ExportPath -NoTypeInformation

}

Else

{

# Print sample output to screen

$Results | select * | select -first 1 

}




Write-Output "Exported $EntryCount credentials"