Skip to content

Instantly share code, notes, and snippets.

@vermashi
Created April 20, 2018 01:06
Show Gist options
  • Save vermashi/3745c8503a2166f0a5eb9d72c2e2a2fc to your computer and use it in GitHub Desktop.
Save vermashi/3745c8503a2166f0a5eb9d72c2e2a2fc to your computer and use it in GitHub Desktop.
Retrieve the encryption secret (aka passphrase) from Azure Key Vault
Param(
[Parameter(Mandatory = $true,
HelpMessage="ResourceGroup name of the vm")]
[ValidateNotNullOrEmpty()]
[string]$rgName,
[Parameter(Mandatory = $true,
HelpMessage="VM name")]
[ValidateNotNullOrEmpty()]
[string]$vmName,
[Parameter(Mandatory = $true,
HelpMessage="Location where the retrieved secret should be written to")]
[ValidateNotNullOrEmpty()]
[string]$secretFilePath
)
#Login-AzureRmAccount;
#Install Active directory module
Install-Module -Name MSOnline;
#Get current logged in user and active directory tenant details
$ctx = Get-AzureRmContext;
$adTenant = $ctx.Tenant.Id;
$currentUser = $ctx.Account.Id
#Get encryption secret url and kek url from VM's encryption settings
$vm = Get-AzureRmVm -ResourceGroupName $rgName -Name $vmName;
$secretUrl = $vm.StorageProfile.OsDisk.EncryptionSettings.DiskEncryptionKey.SecretUrl;
$secretUrl = [System.Uri]$secretUrl;
#if encrypted using KEK
if($vm.StorageProfile.OsDisk.EncryptionSettings.KeyEncryptionKey)
{
$kekUrl = $vm.StorageProfile.OsDisk.EncryptionSettings.KeyEncryptionKey.KeyUrl
}
#Retrieve keyvault name, secret name and secret version from secret URL
$keyVaultName = $secretUrl.Host.Split('.')[0];
$secretName = $secretUrl.Segments[2].TrimEnd('/');
$secretVersion = $secretUrl.Segments[3].TrimEnd('/');
#Set permissions for the current user to unwrap keys and retrieve secrets from KeyVault
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -PermissionsToKeys all -PermissionsToSecrets all -UserPrincipalName $currentUser;
#Retrieve secret from KeyVault secretUrl
$keyVaultSecret = Get-AzureKeyVaultSecret -VaultName $keyVaultName -Name $secretName -Version $secretVersion;
$secretBase64 = $keyVaultSecret.SecretValueText;
#Unwrap secret if the secret is wrapped with KEK
if($kekUrl)
{
########################################################################################################################
# Initialize ADAL libraries and get authentication context required to make REST API called against KeyVault REST APIs.
########################################################################################################################
# Set well-known client ID for AzurePowerShell
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
# Set redirect URI for Azure PowerShell
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
# Set Resource URI to Azure Service Management API
$resourceAppIdURI = "https://vault.azure.net"
# Set Authority to Azure AD Tenant
$authority = "https://login.windows.net/$adTenant"
# Create Authentication Context tied to Azure AD Tenant
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
# Acquire token
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId, $redirectUri, "Auto")
# Generate auth header
$authHeader = $authResult.CreateAuthorizationHeader()
# Set HTTP request headers to include Authorization header
$headers = @{'x-ms-version'='2014-08-01';"Authorization" = $authHeader}
########################################################################################################################
# 1. Retrieve the secret from KeyVault
# 2. If Kek is not NULL, unwrap the secret with Kek by making KeyVault REST API call
# 3. Convert Base64 string to bytes and write to the BEK file
########################################################################################################################
#Call KeyVault REST API to Unwrap
$jsonObject = @"
{
"alg": "RSA-OAEP",
"value" : "$secretBase64"
}
"@
$unwrapKeyRequestUrl = $kekUrl+ "/unwrapkey?api-version=2015-06-01";
$result = Invoke-RestMethod -Method POST -Uri $unwrapKeyRequestUrl -Headers $headers -Body $jsonObject -ContentType "application/json";
#Convert Base64Url string returned by KeyVault unwrap to Base64 string
$secretBase64Url = $result.value;
$secretBase64 = $secretBase64Url.Replace('-', '+');
$secretBase64 = $secretBase64.Replace('_', '/');
if($secretBase64.Length %4 -eq 2)
{
$secretBase64+= '==';
}
elseif($secretBase64.Length %4 -eq 3)
{
$secretBase64+= '=';
}
}
if($secretFilePath)
{
$bekFileBytes = [System.Convert]::FromBase64String($secretBase64);
[System.IO.File]::WriteAllBytes($secretFilePath,$bekFileBytes);
}
@LukeCarrier
Copy link

Thank you -- you saved me a lot of misery figuring this out. The ADE docs are terrible!

@waxb
Copy link

waxb commented Jun 28, 2021

ADE itself is terrible!

@gamlielalon1983
Copy link

Hi
when trying to run the script I get
ou cannot call a method on a null-valued expression.
At line:40 char:1

  • $keyVaultName = $secretUrl.Host.Split('.')[0];
  •   + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull
    
    

I guess its becuase the encryption settings is empty but from checking the VM the disk is encrypted.

happy if you can assist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment