Generate PowerShell Script to Download Multiple KeyVault with its data into Local Storage

Niral Dave 25 Reputation points
2023-05-19T07:09:35.5766667+00:00

Hello Team,
Greetings of the Day!!!

Thankyou in advance for any support or suggestions.

We have created a PowerShell script which downloads multiple key vaults to local storage. Output is happening as per the script, it creates a separate folders for all keyvault with the date&time it is generated but when we gone through the file all Keys, Secrets & Certificates files are empty. We are in the process to understand the behavior that why it downloads empty files. We have tried to manually restore keys to keyvault but got error about file extension.

Code :-

# Define the subscription ID and resource group
$subscriptionId = "05a78749-1cf4-42f5-abfc-c778b2fc69c5"
$resourceGroup = "Patanjali_RG"

# Define the key vault names
$keyVaultNames = @("AarthikKunjika", "PradesKunjika", "VyavhaarKunjika")

# Get the current date and time
$currentDateTime = Get-Date -Format "yyyyMMdd_HHmmss"

# Create a folder based on the current date and time
$folderName = "KeyVaultBackup_$currentDateTime"
New-Item -ItemType Directory -Path $folderName | Out-Null

# Loop through each key vault and download the keys, secrets, and certificates
foreach ($keyVaultName in $keyVaultNames) {
    # Get the key vault
    $keyVault = Get-AzKeyVault -VaultName $keyVaultName -SubscriptionId $subscriptionId

    # Get the keys from the key vault
    $keyVaultKeys = Get-AzKeyVaultKey -VaultName $keyVault.VaultName

    # Get the secrets from the key vault
    $keyVaultSecrets = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName

    # Get the certificates from the key vault
    $keyVaultCertificates = Get-AzKeyVaultCertificate -VaultName $keyVault.VaultName

    # Create a folder for the key vault within the main folder
    $keyVaultFolder = Join-Path -Path $folderName -ChildPath $keyVaultName
    New-Item -ItemType Directory -Path $keyVaultFolder | Out-Null

    # Download and save the keys
    foreach ($key in $keyVaultKeys) {
        $keyValue = Get-AzKeyVaultKey -VaultName $keyVault.VaultName -Name $key.Name -Version $key.Version
        $keyFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($key.Name).txt"
        $keyValue.KeyMaterial | Out-File -FilePath $keyFilePath
    }

    # Download and save the secrets
    foreach ($secret in $keyVaultSecrets) {
        $secretValue = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name $secret.Name -Version $secret.Version
        $secretFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($secret.Name).txt"
        $secretValue.SecretValue | Out-File -FilePath $secretFilePath
    }

    # Download and save the certificates
    foreach ($certificate in $keyVaultCertificates) {
        $certificateValue = Get-AzKeyVaultCertificate -VaultName $keyVault.VaultName -Name $certificate.Name -Version $certificate.Version
        $certificateFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($certificate.Name).cer"
        $certificateValue.Cer | Out-File -FilePath $certificateFilePath
    }
}

# Output the backup folder path
$folderName

Let us know. If we are missing out anything in script.

Thankyou for supporting : )

Azure Key Vault
Azure Key Vault
An Azure service that is used to manage and protect cryptographic keys and other secrets used by cloud apps and services.
1,448 questions
Windows for business Windows Server User experience PowerShell
0 comments No comments
{count} votes

Accepted answer
  1. Alistair Ross 7,466 Reputation points Microsoft Employee
    2023-05-19T09:18:05.4733333+00:00

    Hello @Niral Dave

    Focusing on keys, I can see you call the Get-AzKeyVaultKey cmdlet.

    $keyValue = Get-AzKeyVaultKey -VaultName $keyVault.VaultName -Name $key.Name -Version $key.Version
    
    

    in this cmdlet, you have specified the parameter -Version $key.version. However the cmdlet and parameters you use to populate the $keyVaultKeys variable does not return any key version. If you want to just return the current version, the take the -version parameter out. This is the same for secrets and certificates

    https://learn.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultkey?view=azps-9.7.1

    Also, you have the line:

    $keyValue.KeyMaterial | Out-File -FilePath $keyFilePath
    
    
    
    

    I do not know where you have got the value KeyMaterial from as it is not a property or method for the TypeName: Microsoft.Azure.Commands.KeyVault.Models.PSKeyVaultKey.

    If you want to output the key value, then you need to use the -outfile parameter with Get-AzKeyVaultKey. This will output the key as a .pem file. (Though you can specifiy .txt if needed)

    I've updated your script and added options for your certificate output.

    # Define the subscription ID and resource group
    $subscriptionId = "05a78749-1cf4-42f5-abfc-c778b2fc69c5"
    $resourceGroup = "Patanjali_RG"
    
    # Define the key vault names
    $keyVaultNames = @("AarthikKunjika", "PradesKunjika", "VyavhaarKunjika")
    
    # Get the current date and time
    $currentDateTime = Get-Date -Format "yyyyMMdd_HHmmss"
    
    # Create a folder based on the current date and time
    $folderName = "KeyVaultBackup_$currentDateTime"
    New-Item -ItemType Directory -Path $folderName | Out-Null
    
    # Loop through each key vault and download the keys, secrets, and certificates
    foreach ($keyVaultName in $keyVaultNames) {
        # Get the key vault
        $keyVault = Get-AzKeyVault -VaultName $keyVaultName -SubscriptionId $subscriptionId
    
        # Get the keys from the key vault
        $keyVaultKeys = Get-AzKeyVaultKey -VaultName $keyVault.VaultName
    
        # Get the secrets from the key vault
        $keyVaultSecrets = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName
    
        # Get the certificates from the key vault
        $keyVaultCertificates = Get-AzKeyVaultCertificate -VaultName $keyVault.VaultName
    
        # Create a folder for the key vault within the main folder
        $keyVaultFolder = Join-Path -Path $folderName -ChildPath $keyVaultName
        New-Item -ItemType Directory -Path $keyVaultFolder | Out-Null
    
        # Download and save the keys (This will also download certificate keys)
        foreach ($key in $keyVaultKeys) {
            $keyFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($key.Name).pem"
            Get-AzKeyVaultKey -VaultName $keyVault.VaultName -Name $key.Name -OutFile $keyFilePath
        }
    
        # Download and save the secrets (This will also download certificate secrets)
         foreach ($secret in $keyVaultSecrets) {
            $secretFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($secret.Name).txt"
            $secretValue = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name $secret.Name -AsPlainText
            $secretValue | Out-File -FilePath $secretFilePath
        }
     
        # Download and save the certificates
         foreach ($certificate in $keyVaultCertificates) {
    
            # As a PFX File
            $certificateFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($certificate.Name).pfx"
            $certificateBase64 = Get-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name $certificate.Name -AsPlainText
            $certificateBytes = [Convert]::FromBase64String($certificateBase64)
            Set-Content -Path $certificateFilePath -Value $certificateBytes -AsByteStream
    
            # As a CER File
            $certificateFilePath = Join-Path -Path $keyVaultFolder -ChildPath "$($certificate.Name).cer"
            $certificateValue = Get-AzKeyVaultCertificate -VaultName $keyVault.VaultName -Name $certificate.Name
            $certificateValueBytes = $certificateValue.Certificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
            [System.IO.File]::WriteAllBytes($certificateFilePath, $certificateValueBytes)
        } 
    }
    
    # Output the backup folder path
    $folderName
    
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.