Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save killejay/49bf07e94baecc1e409d620822ae79cc to your computer and use it in GitHub Desktop.
Save killejay/49bf07e94baecc1e409d620822ae79cc to your computer and use it in GitHub Desktop.
Retrieve Encryption key via secret URL
# Sample Script Run command (could run without escalation):
# ./RetreiveEncryptionSecretViaUrl.ps1 -secretUrl xxx -kekUrl yyy -secretFilePath Output-KEK-key -vaultrg Resource-group-of-keyvault
Param(
[Parameter(Mandatory = $true,
HelpMessage="keyvault resource group name")]
[ValidateNotNullOrEmpty()]
[string]$vaultrg,
[Parameter(Mandatory = $true,
HelpMessage="URL to the secret stored in the keyvault")]
[ValidateNotNullOrEmpty()]
[string]$secretUrl,
[Parameter(Mandatory = $false,
HelpMessage="URL to the KEK")]
[ValidateNotNullOrEmpty()]
[string]$kekUrl,
[Parameter(Mandatory = $true,
HelpMessage="Location where the retrieved secret should be written to")]
[ValidateNotNullOrEmpty()]
[string]$secretFilePath
)
# if ((Test-Path -Path 'activedirectory-lib' -PathType Container))
# {
# Write-Output "Previous temp lib folder detected, proceed to delete."
# Remove-Item -Path 'activedirectory-lib' -Force -Recurse
# }
#Login-AzureRmAccount;
#Install Active directory module
#Install-Module -Name MSOnline;
#Tested no need to load MSOnline lib.
#Get current logged in user and active directory tenant details
$ctx = Get-AzContext;
$adTenant = $ctx.Tenant.Id;
$currentUser = $ctx.Account.Id
#Parse the secret URL
$secretUri = [System.Uri] $secretUrl;
#Retrieve keyvault name, secret name and secret version from secret URL
$keyVaultName = $secretUri.Host.Split('.')[0];
$secretName = $secretUri.Segments[2].TrimEnd('/');
$secretVersion = $secretUri.Segments[3].TrimEnd('/');
#Set permissions for the current user to unwrap keys and retrieve secrets from KeyVault
$KeyVault = Get-AzKeyVault -VaultName $keyVaultName -ResourceGroupName $vaultrg;
$acl = $KeyVault.AccessPolicies;
$currentacl = $acl | Where-Object { $_.DisplayName -match $currentUser };
$aclp2k = $currentacl.PermissionsToKeys + "unwrapKey"
$aclp2s = $currentacl.PermissionsToSecrets + "get"
#Set-AzKeyVaultAccessPolicy -VaultName $keyVaultName -PermissionsToKeys $aclp2k -PermissionsToSecrets $aclp2s -UserPrincipalName $currentUser;
#Retrieve secret from KeyVault secretUrl
$keyVaultSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $secretName -Version $secretVersion -AsPlainText;
$secretBase64 = $keyVaultSecret;
#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.
########################################################################################################################
# Get the Lib from external, using the traditional 2.29 version instead of the latest.
Invoke-WebRequest -Uri 'https://www.nuget.org/api/v2/package/Microsoft.IdentityModel.Clients.ActiveDirectory/2.29.0' -OutFile 'microsoft.identitymodel.clients.activedirectory.2.29.0.zip'
Expand-Archive -LiteralPath 'microsoft.identitymodel.clients.activedirectory.2.29.0.zip' -DestinationPath 'activedirectory-lib/'
Add-Type -Path 'activedirectory-lib/lib/net45/Microsoft.IdentityModel.Clients.ActiveDirectory.dll'
# 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=7.1";
$result = Invoke-RestMethod -Method POST -Uri $unwrapKeyRequestUrl -Headers $headers -Body $jsonObject -ContentType "application/json";
#Convert Base64Url string returned by KeyVault unwrap to Base64 string
$secretBase64 = $result.value;
}
$secretBase64 = $secretBase64.Replace('-', '+');
$secretBase64 = $secretBase64.Replace('_', '/');
if($secretBase64.Length %4 -eq 2)
{
$secretBase64+= '==';
}
elseif($secretBase64.Length %4 -eq 3)
{
$secretBase64+= '=';
}
# Modified to prevent fallback use absulte address
if($secretFilePath)
{
$bekFileBytes = [System.Convert]::FromBase64String($secretBase64);
$dec_secretBase64 = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($secretBase64));
Write-Output "Your original base64-wrapped secret is: "`r$secretBase64`n""
if (![string]::IsNullOrEmpty($dec_secretBase64)){
Write-Output "Your decrypyted BEK key is: "`r$($dec_secretBase64)""
$confirmation = Read-Host "Generate the key file to current folder? (y/n)"
if ($confirmation -eq 'y') {
Out-File -FilePath $secretFilePath -InputObject $dec_secretBase64
}
Remove-Item -Path 'microsoft.identitymodel.clients.activedirectory.2.29.0.zip' -Force
Write-Output "Script run finished."`r">>Remerber to close this PowerShell windows, and then delete the activedirectory-lib folder manually."
}
else {
Write-Output "!! Retrive Key failed, please check KeyVault access permission or other settings."
Remove-Item -Path 'activedirectory-lib' -Force -Recurse
}
}
@killejay
Copy link
Author

killejay commented Apr 1, 2021

Example:

C:\Scripts\RetreiveEncryptionSecretViaUrl.ps1 -vaultrg testrg -secretUrl https://.vault.azure.net/secrets//* -kekUrl https://.vault.azure.net:443/keys//*** -secretFilePath C:\BEK\TestKEK**

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