Search code examples
azurepowershellazure-keyvaultprivate-keypowershell-core

How to store and retrieve an SSH Private Key in Azure Key Vault


Question

Is there a correct way to store an RSA Private Key in Azure Key Vault such that I can retrieve it (under a different user, on a different device) using powershell cmdlets (ideally the az.KeyVault module).

Context

I have a private SSH key used to connect to an external SFTP service. I'd like to store this in Azure Key Vault, and allow my Azure Function to read this for when it needs to connect to SFTP.

Originally I uploaded this RSA private key as a key... but found that when I then fetched it the PEM envelope was for a public key, and the value very different to what I'd uploaded.

I found this post saying how to use the AZ CLI to store and retrieve a private key; treating it as a secret instead of a key. This is what I want... but as my azure function is written in PowerShell I'm hoping to use the corresponding PWSH cmdlets; though those don't have an option to specify a source file as the CLI does.

Looking at the docs I found this storing multi-line secrets in Azure Key Vault with powershell... but that says to use ConvertTo-SecureString; which I believe would mean that the value could only be decrypted by the same user/machine combo who created it; which doesn't make sense for most scenarios involving Key Vault (i.e. why not store the secret on the machine if it's dependent on the machine anyway), and doesn't allow me to set the secret from my machine and have it available to my Azure Function.

I can of course simply replace the line breaks in the original PEM with some other delimiter (e.g. pipes) then revert this when fetching the secret; but that feels rather hacky.


Solution

  • I just realized I'd misunderstood... I thought the conversion to a secure string was to store it encoded as a secure string; rather it's just because the function's parameter expects a secure string.

    The private key is stored and retrieved as expected... The MS documentation's point about line breaks being formatted as escaped characters (i.e. '\n') is incorrect; they're preserved as expected.

    Set the secret from a value in file

    $pem = (Get-Content '.\myPrivateKey.pem' -Raw)
    Set-AzKeyVaultSecret -VaultName 'MyKeyVault' -Name 'MySftpPrivateKey' `
        -SecretValue ($pem | ConvertTo-SecureString -AsPlainText -Force)
    

    Retrieving the private key

    $myPlaintextPrivateKey = Get-AzKeyVaultSecret -VaultName `
        'MyKeyVault' -Name 'MySftpPrivateKey' -AsPlainText
    

    Additional Info

    Per @jkix's comment, to run the above you'll need to have installed the Azure PS module and authenticated. To do that:

    # Run this once to get the Azure module on your machine
    Install-Module Az
    
    # Run this once per session to load the Azure module
    Import-Module Az
    
    # Run this once per session to authenticate 
    # (opens a browser for you to complete authentication steps through)
    Connect-AzAccount
    # Note: if you're not using your own account, or are not in an interactive
    # session, see documentation for details on other options, such as
    # using a Service Principal (aka Entra Enterprise App):
    # https://learn.microsoft.com/en-us/powershell/module/az.accounts/connect-azaccount?view=azps-11.5.0#example-3-connect-to-azure-using-a-service-principal-account
    
    # Says which subscription we're working with
    $MySubscriptionGuid = '00000000-0000-0000-0000-000000000000' #amend to your needs
    Set-AzContext -SubscriptionId $MySubscriptionGuid