SecretBackup.psm1

<#
.SYNOPSIS
Exports secrets from a specified vault to a JSON file.

.DESCRIPTION
This function exports secrets from a specified vault to a JSON file. It retrieves secret information from the vault and converts it to a JSON format for export.

.PARAMETER VaultName
Specifies the name of the vault from which to export secrets. This parameter is mandatory.

.PARAMETER OutPath
Specifies the output path where the JSON file will be saved. If not provided, the current location will be used as the default output path.

.EXAMPLE
Export-Secret -VaultName 'MyVault' -OutPath 'C:\Backups'
Exports secrets from the 'MyVault' vault and saves the JSON file to the 'C:\Backups' directory.

.EXAMPLE
Export-Secret -VaultName 'MyVault'
Exports secrets from the 'MyVault' vault and saves the JSON file to the current location.

.NOTES
Exports secretes in plain text. Make sure you protect the exported data.
#>

function Export-Secret {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $VaultName,
        [string]
        $OutPath = (Get-Location).Path
    )
    Test-VaultAccess -VaultName $VaultName

    $Data = New-Object -TypeName System.Collections.ArrayList

    $AllSecrets = Get-SecretInfo -Vault $VaultName
    foreach ($Secret in $AllSecrets) {
        if ($Secret.Type -eq 'String' -or $Secret.Type -eq 'SecureString') {
            $Obj = [PSCustomObject]@{
                Name     = $Secret.Name
                Type     = [string]$Secret.Type
                Secret   = Get-Secret -Vault $VaultName -Name $Secret.Name -AsPlainText
                Metadata = $Secret.Metadata #| ConvertTo-Json -Compress
            }
        } elseif ($Secret.Type -eq 'PSCredential') {
            $SecInfo = Get-Secret -Vault $VaultName -Name $Secret.Name -AsPlainText
            $Obj = [PSCustomObject]@{
                Name     = $Secret.Name
                Type     = [string]$Secret.Type
                Secret   = @{
                    UserName = $SecInfo.UserName
                    Password = $SecInfo.Password | ConvertFrom-SecureString -AsPlainText
                }
                Metadata = $Secret.Metadata #| ConvertTo-Json -Compress
            }
        } else {
            'Secret {0} of type {1} is not supported' -f $Secret.Name, $Secret.Type | Write-Warning
        }
        $Data.Add($Obj) | Out-Null
    }
    $outFileName = 'Vault_Backup_{0}.json' -f (Get-Date).ToString('yyyyMMdd_HHmm')
    $outFile = Join-Path -Path $OutPath -ChildPath $outFileName
    $Data | ConvertTo-Json | Out-File -FilePath $outFile
    if ($?) {
        'Successfully exported backup to: {0}' -f $outFile | Write-Host
    } else {
        'Someting went wrong, export failed' | Write-Error
    }
}
<#
.SYNOPSIS
Imports secrets from a backup file into a specified vault.

.DESCRIPTION
This function imports secrets from a backup file (generated by same module) into a specified vault. It checks if the secret already exists in the vault and either adds it or updates it based on the OverWrite switch parameter.

.PARAMETER VaultName
The name of the vault where the secrets will be imported.

.PARAMETER BackupFile
The path to the backup file containing the secrets to be imported.

.PARAMETER OverWrite
A switch parameter that specifies whether existing secrets in the vault should be overwritten if they already exist.

.EXAMPLE
Import-Secret -VaultName "MyVault" -BackupFile "C:\Path\to\backup.json" -OverWrite
Imports secrets from the specified backup file into the "MyVault" vault, overwriting existing secrets if they already exist.
#>

function Import-Secret {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $VaultName,
        [Parameter(Mandatory)]
        [string]
        $BackupFile,
        [switch]
        $OverWrite
    )
    Test-VaultAccess -VaultName $VaultName
    # Test-ValidJSONInput -JSONFile $BackupFile
    $RestoredCount = 0
    $JSONData = Get-Content -Path $BackupFile -Raw | ConvertFrom-Json
    foreach ($Secret in $JSONData) {
        if (Get-SecretInfo -Vault $VaultName -Name $Secret.Name) {
            $SecretExists = $true
        } else {
            $SecretExists = $false
        }
        if (-not $SecretExists -or $OverWrite) {
            $Metadata = $Secret.Metadata | ConvertTo-Json | ConvertFrom-Json -AsHashtable
            if ($Secret.Type -eq 'String' -or $Secret.Type -eq 'SecureString') {
                Set-Secret -Vault $VaultName -Name $Secret.Name -Secret $Secret.Secret -Metadata $Metadata
                $RestoredCount ++
            } elseif ($Secret.Type -eq 'PSCredential') {
                $username = $Secret.Secret.UserName
                $password = $Secret.Secret.Password | ConvertTo-SecureString -AsPlainText
                $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
                Set-Secret -Vault $VaultName -Name $Secret.Name -Secret $credential -Metadata $Metadata
                $RestoredCount ++
            } 
        }
    }
    "Imported $RestoredCount secrets" | Write-Host
}
function Test-ValidJSONInput {
    param (
        $JSONFile
    )
    # TODO Check in depth with json schema
    if (-not(Test-Json -Json $JSONFile -ErrorAction SilentlyContinue)) {
        Write-Error 'Provided backup file is corrupted and not supported' -ErrorAction Stop
    }
}
function Test-VaultAccess {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string]
        $VaultName
    )
    if (-not(Get-Command Test-SecretVault -ErrorAction SilentlyContinue)) {
        'SecretManagement module is not found, aborting' | Write-Error -ErrorAction Stop
    }
    
    Try {
        Test-SecretVault -Name $VaultName -ErrorAction Stop | Out-Null
    } Catch {
        "Unable to access Vault! `n{0}" -f $Error[0] | Write-Error -ErrorAction Stop
    }
}