I'm attempting to create a self signed certificate in KeyVault using the "Self" issuer.
$policy = New-AzureKeyVaultCertificatePolicy -SubjectName "CN=$($certificateName)" -IssuerName "Self" -ValidityInMonths 12
$policy.Exportable = $true
Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy
However, when getting the certificate back it doesn't appear to have a private key.
Creating certificates directly in KeyVault doesn't seem hugely covered online, after digging into the rest API documentation and source code for the powershell cmdlets, I'm stumped.
I'm hoping it's something simple I've missed, as I wish to avoid creating the certificate locally..
If you'd like to retrieve your certificate along with its private key, then you can export it to a PFX file (with an empty password) on your disk via:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "\$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
[IO.File]::WriteAllBytes($pfxPath, $pfxUnprotectedBytes)
If you'd like to view just the private key itself in-memory without writing to disk, then try:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "\$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfx.PrivateKey.ExportParameters($true)
which will show the private parameters in addition to the exponent and modulus.
If you'd like to protect the PFX file on disk with your own password (as per the "Retrieve pfx file & add password back" instructions in this blog post), then try:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "\$certificateName.pfx"
$password = "my-password"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxProtectedBytes = $pfx.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
[IO.File]::WriteAllBytes($pfxPath, $pfxProtectedBytes)
As mentioned in the REST API docs here and here, Azure Key Vault (AKV) represents a given X.509 certificate via three interrelated resources: an AKV-certificate, an AKV-key, and an AKV-secret. All three will share the same name and the same version - to verify this, examine the Id
, KeyId
, and SecretId
properties in the response from Get-AzureKeyVaultCertificate
.
Each of these 3 resources provide a different perspective for viewing a given X.509 cert:
n
and e
), as well as other cert metadata (thumbprint, expiry date, subject name, and so on). In PowerShell, you can obtain this via:(Get-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName).Certificate
(Get-AzureKeyVaultKey -VaultName $vaultName -Name $certificateName).Key
(Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName).SecretValueText