About Me

My photo
I am MCSE in Data Management and Analytics with specialization in MS SQL Server and MCP in Azure. I have over 13+ years of experience in IT industry with expertise in data management, Azure Cloud, Data-Canter Migration, Infrastructure Architecture planning and Virtualization and automation. Contact me if you are looking for any sort of guidance in getting your Infrastructure provisioning automated through Terraform. I sometime write for a place to store my own experiences for future search and read by own blog but can hopefully help others along the way. Thanks.

How to encrypt virtual disks on a Windows VM using Power Shell

How to encrypt & Disable virtual disks on a Windows VM using Power Shell


Azure Disk Encryption (ADE) leverages the industry standard BitLocker feature of Windows and the DM-Crypt feature of Linux to provide OS and data disk encryption to help protect and safeguard your data and help meet your organizational security and compliance commitments in customer Azure key vault.
 
 Managed Disks are encrypted at rest by default using Azure Storage Service Encryption using keys managed by Azure.
If you are using Managed Disks, Microsoft recommends you to use ADE if you want to encrypt disks and safeguard your encryption keys in Azure key vault including encryption of the ephemeral (temp) disks. You can completely control and manage your disk encryption keys and secrets in your key vault subscription while ensuring that all data in the virtual machine disks are encrypted at rest.



https://docs.microsoft.com/en-us/azure/security/azure-security-disk-encryption-faq
Azure Disk Encryption uses the BitLocker external key protector for encrypting Windows IaaS VMs.
 When you need encryption to be enabled on a running virtual machine in Azure,
 Azure Disk Encryption generates and writes the BitLocker encryption keys to an Azure key vault.
 And we can execute this entire process in two fairly simple high level steps.
 Managing those encryption keys in your key vault requires Azure AD authentication.

 And for that purpose,
  we have to create an Azure AD application,
  and for authentication purposes
   we can either use client secret based authentication or client certificate based Azure AD authentication.


For enhanced virtual machine (VM) security and compliance, virtual disks in Azure can be encrypted.
 Disks are encrypted using cryptographic keys that are secured in an Azure Key Vault.
You control these cryptographic keys and can audit their use.
This article details how to encrypt virtual disks on a Windows VM using Azure PowerShell. You can also encrypt a Linux VM using the Azure CLI 2.0.


Overview of disk encryption
  ==========================

Virtual disks on Windows VMs are encrypted at rest using Bitlocker.

Secure Azure virtual machines and disks
 Again, In Azure we have the ability to secure our virtual machines and the disk. When we encrypt our Azure Virtual Machines, we encrypt both the OS and data disk at rest. Our Windows Virtual Machines are encrypted using BitLocker and the Linux Virtual Machines are encrypted using dm-crypt. And this process uses the Azure Key Vault.
 But before you start encrypting all your virtual machines, there are few things you need to be aware of. First, we can only encrypt our standard virtual machines. Our basic virtual machines cannot be encrypted.
And only virtual machines that have been created in the Azure Resource Manager or ARM portal can be encrypted. Your server has to be at least a Server 2008 R2 and above to be encrypted. And for those of you who are running desktop clients in Azure, only Windows 8 and Windows 10 clients can also be encrypted. 
 You must make sure your Key Vault and your virtual machines are in the same region and in the same subscription.
 Let's take a look at the Encryption Workflow. 
 
We as the administrator send the PowerShell cmdlet to encrypt our virtual machine. Within Azure storage, the OS and the data disk are also encrypted. And the encryption keys are kept in the key vault. And these keys are written to the key vault by an application. 






There is no charge for encrypting virtual disks in Azure.

1.Cryptographic keys are stored in Azure Key Vault using software-protection, or you can import or generate your keys in Hardware Security Modules (HSMs) certified to FIPS 140-2 level 2 standards. These cryptographic keys are used to encrypt and decrypt virtual disks attached to your VM.
2.You retain control of these cryptographic keys and can audit their use.
 An Azure Active Directory service principal provides a secure mechanism for issuing these cryptographic keys as VMs are powered on and off.

The process for encrypting a VM is as follows:-

----------------------------------------------------------
  1. Create a cryptographic key in an Azure Key Vault.
  2. Configure the cryptographic key to be usable for encrypting disks.
  3. To read the cryptographic key from the Azure Key Vault, create an Azure Active Directory service principal with the appropriate permissions.
  4. Issue the command to encrypt your virtual disks, specifying the Azure Active Directory service principal and appropriate cryptographic key to be used.
  5. The Azure Active Directory service principal requests the required cryptographic key from Azure Key Vault.
  6. The virtual disks are encrypted using the provided cryptographic key.


Here i have a VM Named --> sqlnode1 which is under a resource group name --> rakctlrg and the location is centralus.

The OS disk is not encrypted initially as shown in the figure below..



you can refer below blog to understand the logic.

https://docs.microsoft.com/en-us/azure/virtual-machines/windows/encrypt-disks



Disk encryption relies on the following additional components:

1. Azure Key Vault - used to safeguard cryptographic keys and secrets used for the disk encryption/decryption process.
If one exists, you can use an existing Azure Key Vault. You do not have to dedicate a Key Vault to encrypting disks.
To separate administrative boundaries and key visibility, you can create a dedicated Key Vault.

2.Azure Active Directory - handles the secure exchanging of required cryptographic keys and authentication for requested actions.
You can typically use an existing Azure Active Directory instance for housing your application.
The service principal provides a secure mechanism to request and be issued the appropriate cryptographic keys. You are not developing an actual application that integrates with Azure Active Directory.

if working on existing VM, ensure that VM is up and working fine.


Param(
  [Parameter(Mandatory = $true,
             HelpMessage="Name of the resource group to which the KeyVault belongs to.  A new resource group with this name will be created if one doesn't exist")]
  [ValidateNotNullOrEmpty()]
  [string]$resourceGroupName,

  [Parameter(Mandatory = $true,
             HelpMessage="Name of the KeyVault in which encryption keys are to be placed. A new vault with this name will be created if one doesn't exist")]
  [ValidateNotNullOrEmpty()]
  [string]$keyVaultName,

  [Parameter(Mandatory = $true,
             HelpMessage="Location of the KeyVault. Important note: Make sure the KeyVault and VMs to be encrypted are in the same region / location.")]
  [ValidateNotNullOrEmpty()]
  [string]$location,

  [Parameter(Mandatory = $true,
             HelpMessage="Name of the AAD application that will be used to write secrets to KeyVault. A new application with this name will be created if one doesn't exist. If this app already exists, pass aadClientSecret parameter to the script")]
  [ValidateNotNullOrEmpty()]
  [string]$aadAppName,

  [Parameter(Mandatory = $false,
             HelpMessage="Client secret of the AAD application that was created earlier")]
  [ValidateNotNullOrEmpty()]
  [string]$aadClientSecret,

  [Parameter(Mandatory = $false,
             HelpMessage="Identifier of the Azure subscription to be used. Default subscription will be used if not specified.")]
  [ValidateNotNullOrEmpty()]
  [string]$subscriptionId,

  [Parameter(Mandatory = $false,
             HelpMessage="Name of optional key encryption key in KeyVault. A new key with this name will be created if one doesn't exist")]
  [ValidateNotNullOrEmpty()]
  [string]$keyEncryptionKeyName

)

########################################################################################################################
# Section1:  Log-in to Azure and select appropriate subscription.
########################################################################################################################


    Write-Host 'Please log into Azure now' -foregroundcolor Green;
    Login-AzureRmAccount -ErrorAction "Stop" 1> $null;

    if($subscriptionId)
    {
        Select-AzureRmSubscription -SubscriptionId $subscriptionId;
    }


########################################################################################################################
# Section2:  Create AAD app . Fill in $aadClientSecret variable if AAD app was already created
########################################################################################################################


    # Check if AAD app with $aadAppName was already created
    $SvcPrincipals = (Get-AzureRmADServicePrincipal -SearchString $aadAppName);
    if(-not $SvcPrincipals)
    {
        # Create a new AD application if not created before
        $identifierUri = [string]::Format("http://localhost:8080/{0}",[Guid]::NewGuid().ToString("N"));
        $defaultHomePage = 'http://contoso.com';
        $now = [System.DateTime]::Now;
        $oneYearFromNow = $now.AddYears(1);
        $aadClientSecret = [Guid]::NewGuid();

        Write-Host "Creating new AAD application ($aadAppName)";
        $ADApp = New-AzureRmADApplication -DisplayName $aadAppName -HomePage $defaultHomePage -IdentifierUris $identifierUri  -StartDate $now -EndDate $oneYearFromNow -Password $aadClientSecret;
        $servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $ADApp.ApplicationId;
        $SvcPrincipals = (Get-AzureRmADServicePrincipal -SearchString $aadAppName);
        if(-not $SvcPrincipals)
        {
            # AAD app wasn't created
            Write-Error "Failed to create AAD app $aadAppName. Please log-in to Azure using Login-AzureRmAccount  and try again";
            return;
        }
        $aadClientID = $servicePrincipal.ApplicationId;
        Write-Host "Created a new AAD Application ($aadAppName) with ID: $aadClientID ";
    }
    else
    {
        if(-not $aadClientSecret)
        {
            $aadClientSecret = Read-Host -Prompt "Aad application ($aadAppName) was alerady created, input corresponding aadClientSecret and hit ENTER. It can be retrieved from https://manage.windowsazure.com portal" ;
        }
        if(-not $aadClientSecret)
        {
            Write-Error "Aad application ($aadAppName) was alerady created. Re-run the script by supplying aadClientSecret parameter with corresponding secret from https://manage.windowsazure.com portal";
            return;
        }
        $aadClientID = $SvcPrincipals[0].ApplicationId;
    }

# Before proceeding to Section3, make sure $aadClientID  and $aadClientSecret have valid values
########################################################################################################################
# Section3:  Create KeyVault or setup existing keyVault
########################################################################################################################

    Try
    {
        $resGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue;
    }
    Catch [System.ArgumentException]
    {
        Write-Host "Couldn't find resource group:  ($resourceGroupName)";
        $resGroup = $null;
    }

    #Create a new resource group if it doesn't exist
    if (-not $resGroup)
    {
        Write-Host "Creating new resource group:  ($resourceGroupName)";
        $resGroup = New-AzureRmResourceGroup -Name $resourceGroupName -Location $location;
        Write-Host "Created a new resource group named $resourceGroupName to place keyVault";
    }

    Try
    {
        $keyVault = Get-AzureRmKeyVault -VaultName $keyVaultName -ErrorAction SilentlyContinue;
    }
    Catch [System.ArgumentException]
    {
        Write-Host "Couldn't find Key Vault: $keyVaultName";
        $keyVault = $null;
    }

    #Create a new vault if vault doesn't exist
    if (-not $keyVault)
    {
        Write-Host "Creating new key vault:  ($keyVaultName)";
        $keyVault = New-AzureRmKeyVault -VaultName $keyVaultName -ResourceGroupName $resourceGroupName -Sku Standard -Location $location;
        Write-Host "Created a new KeyVault named $keyVaultName to store encryption keys";
    }
    # Specify privileges to the vault for the AAD application - https://msdn.microsoft.com/en-us/library/mt603625.aspx
    Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ServicePrincipalName $aadClientID -PermissionsToKeys wrapKey -PermissionsToSecrets set;

    Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -EnabledForDiskEncryption;

    $diskEncryptionKeyVaultUrl = $keyVault.VaultUri;
$keyVaultResourceId = $keyVault.ResourceId;

    if($keyEncryptionKeyName)
    {
        Try
        {
            $kek = Get-AzureKeyVaultKey -VaultName $keyVaultName -Name $keyEncryptionKeyName -ErrorAction SilentlyContinue;
        }
        Catch [Microsoft.Azure.KeyVault.KeyVaultClientException]
        {
            Write-Host "Couldn't find key encryption key named : $keyEncryptionKeyName in Key Vault: $keyVaultName";
            $kek = $null;
        }

        if(-not $kek)
        {
            Write-Host "Creating new key encryption key named:$keyEncryptionKeyName in Key Vault: $keyVaultName";
            $kek = Add-AzureKeyVaultKey -VaultName $keyVaultName -Name $keyEncryptionKeyName -Destination Software -ErrorAction SilentlyContinue;
            Write-Host "Created  key encryption key named:$keyEncryptionKeyName in Key Vault: $keyVaultName";
        }

        $keyEncryptionKeyUrl = $kek.Key.Kid;
    }

########################################################################################################################
# Section3:  Displays values that should be used while enabling encryption. Please note these down
########################################################################################################################
    Write-Host "Please note down below aadClientID, aadClientSecret, diskEncryptionKeyVaultUrl, keyVaultResourceId values that will be needed to enable encryption on your VMs " -foregroundcolor Green;
    Write-Host "`t aadClientID: $aadClientID" -foregroundcolor Green;
    Write-Host "`t aadClientSecret: $aadClientSecret" -foregroundcolor Green;
    Write-Host "`t diskEncryptionKeyVaultUrl: $diskEncryptionKeyVaultUrl" -foregroundcolor Green;
    Write-Host "`t keyVaultResourceId: $keyVaultResourceId" -foregroundcolor Green;
    if($keyEncryptionKeyName)
    {
        Write-Host "`t keyEncryptionKeyURL: $keyEncryptionKeyUrl" -foregroundcolor Green;
    }
    Write-Host "Please Press [Enter] after saving values displayed above. They are needed to enable encryption using Set-AzureRmVmDiskEncryptionExtension cmdlet" -foregroundcolor Green;
    Read-Host;

########################################################################################################################
# For each VM you want to encrypt, run the below cmdlet
$vmName = 'rakvmnode1';
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $resourceGroupName -VMName $vmName -AadClientID $aadClientID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl -DiskEncryptionKeyVaultId $keyVaultResourceId;
########################################################################################################################

Verify the disks are encrypted:-

Get-AzureRmVmDiskEncryptionStatus -ResourceGroupName $resourceGroupName -VMName $vmName



This indicates OS disk is encrypted.

Connect to the Virtual Machine and you will find the Machine C:\ drive is getting encrypted.
Encryption of the disk will take time.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~




How to  Disables encryption on an IaaS virtual machine.


$ResourceGroup = "datascienceRs";  -- Your Existing Resource group name where that machine resides

$VMName = "rakvmnode1";
Disable-AzureRMVMDiskEncryption -ResourceGroupName $ResourceGroup -VMName $vmName

This command will take some time and then you will get below Message.

RequestId IsSuccessStatusCode StatusCode ReasonPhrase
--------- ------------------- ---------- ------------
                         True         OK                        OK       



You will observed your disks started Decrypting..







Thanks for Reading.