Tutorial: Secure a web server on a Windows virtual machine in Azure with SSL certificates stored in Key Vault

To secure web servers, a Secure Sockets Layer (SSL) certificate can be used to encrypt web traffic. These SSL certificates can be stored in Azure Key Vault, and allow secure deployments of certificates to Windows virtual machines (VMs) in Azure. In this tutorial you learn how to:

  • Create an Azure Key Vault
  • Generate or upload a certificate to the Key Vault
  • Create a VM and install the IIS web server
  • Inject the certificate into the VM and configure IIS with an SSL binding

Use Azure Cloud Shell

Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. Cloud Shell lets you use either bash or PowerShell to work with Azure services. You can use the Cloud Shell pre-installed commands to run the code in this article without having to install anything on your local environment.

To launch Azure Cloud Shell:

Option Example/Link
Select Try It in the upper-right corner of a code block. Selecting Try It doesn't automatically copy the code to Cloud Shell. Example of Try It for Azure Cloud Shell
Go to https://shell.azure.com or select the Launch Cloud Shell button to open Cloud Shell in your browser. Launch Cloud Shell in a new window
Select the Cloud Shell button on the top-right menu bar in the Azure portal. Cloud Shell button in the Azure portal

To run the code in this article in Azure Cloud Shell:

  1. Launch Cloud Shell.

  2. Select the Copy button on a code block to copy the code.

  3. Paste the code into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS.

  4. Press Enter to run the code.

Launch Azure Cloud Shell

The Azure Cloud Shell is a free interactive shell that you can use to run the steps in this article. It has common Azure tools preinstalled and configured to use with your account.

To open the Cloud Shell, just select Try it from the upper right corner of a code block. You can also launch Cloud Shell in a separate browser tab by going to https://shell.azure.com/powershell. Select Copy to copy the blocks of code, paste it into the Cloud Shell, and press enter to run it.

Overview

Azure Key Vault safeguards cryptographic keys and secrets, such certificates or passwords. Key Vault helps streamline the certificate management process and enables you to maintain control of keys that access those certificates. You can create a self-signed certificate inside Key Vault, or upload an existing, trusted certificate that you already own.

Rather than using a custom VM image that includes certificates baked-in, you inject certificates into a running VM. This process ensures that the most up-to-date certificates are installed on a web server during deployment. If you renew or replace a certificate, you don't also have to create a new custom VM image. The latest certificates are automatically injected as you create additional VMs. During the whole process, the certificates never leave the Azure platform or are exposed in a script, command-line history, or template.

Create an Azure Key Vault

Before you can create a Key Vault and certificates, create a resource group with New-AzResourceGroup. The following example creates a resource group named myResourceGroupSecureWeb in the East US location:

$resourceGroup = "myResourceGroupSecureWeb"
$location = "East US"
New-AzResourceGroup -ResourceGroupName $resourceGroup -Location $location

Next, create a Key Vault with New-AzKeyVault. Each Key Vault requires a unique name, and should be all lower case. Replace mykeyvault in the following example with your own unique Key Vault name:

$keyvaultName="mykeyvault"
New-AzKeyVault -VaultName $keyvaultName `
    -ResourceGroup $resourceGroup `
    -Location $location `
    -EnabledForDeployment

Generate a certificate and store in Key Vault

For production use, you should import a valid certificate signed by trusted provider with Import-AzKeyVaultCertificate. For this tutorial, the following example shows how you can generate a self-signed certificate with Add-AzKeyVaultCertificate that uses the default certificate policy from New-AzKeyVaultCertificatePolicy.

$policy = New-AzKeyVaultCertificatePolicy `
    -SubjectName "CN=www.contoso.com" `
    -SecretContentType "application/x-pkcs12" `
    -IssuerName Self `
    -ValidityInMonths 12

Add-AzKeyVaultCertificate `
    -VaultName $keyvaultName `
    -Name "mycert" `
    -CertificatePolicy $policy 

Create a virtual machine

Set an administrator username and password for the VM with Get-Credential:

$cred = Get-Credential

Now you can create the VM with New-AzVM. The following example creates a VM named myVM in the EastUS location. If they do not already exist, the supporting network resources are created. To allow secure web traffic, the cmdlet also opens port 443.

# Create a VM
New-AzVm `
    -ResourceGroupName $resourceGroup `
    -Name "myVM" `
    -Location $location `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -Credential $cred `
    -OpenPorts 443

# Use the Custom Script Extension to install IIS
Set-AzVMExtension -ResourceGroupName $resourceGroup `
    -ExtensionName "IIS" `
    -VMName "myVM" `
    -Location $location `
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion 1.8 `
    -SettingString '{"commandToExecute":"powershell Add-WindowsFeature Web-Server -IncludeManagementTools"}'

It takes a few minutes for the VM to be created. The last step uses the Azure Custom Script Extension to install the IIS web server with Set-AzVmExtension.

Add a certificate to VM from Key Vault

To add the certificate from Key Vault to a VM, obtain the ID of your certificate with Get-AzKeyVaultSecret. Add the certificate to the VM with Add-AzVMSecret:

$certURL=(Get-AzKeyVaultSecret -VaultName $keyvaultName -Name "mycert").id

$vm=Get-AzVM -ResourceGroupName $resourceGroup -Name "myVM"
$vaultId=(Get-AzKeyVault -ResourceGroupName $resourceGroup -VaultName $keyVaultName).ResourceId
$vm = Add-AzVMSecret -VM $vm -SourceVaultId $vaultId -CertificateStore "My" -CertificateUrl $certURL

Update-AzVM -ResourceGroupName $resourceGroup -VM $vm

Configure IIS to use the certificate

Use the Custom Script Extension again with Set-AzVMExtension to update the IIS configuration. This update applies the certificate injected from Key Vault to IIS and configures the web binding:

$PublicSettings = '{
    "fileUris":["https://raw.githubusercontent.com/Azure-Samples/compute-automation-configurations/master/secure-iis.ps1"],
    "commandToExecute":"powershell -ExecutionPolicy Unrestricted -File secure-iis.ps1"
}'

Set-AzVMExtension -ResourceGroupName $resourceGroup `
    -ExtensionName "IIS" `
    -VMName "myVM" `
    -Location $location `
    -Publisher "Microsoft.Compute" `
    -ExtensionType "CustomScriptExtension" `
    -TypeHandlerVersion 1.8 `
    -SettingString $publicSettings

Test the secure web app

Obtain the public IP address of your VM with Get-AzPublicIPAddress. The following example obtains the IP address for myPublicIP created earlier:

Get-AzPublicIPAddress -ResourceGroupName $resourceGroup -Name "myPublicIPAddress" | select "IpAddress"

Now you can open a web browser and enter https://<myPublicIP> in the address bar. To accept the security warning if you used a self-signed certificate, select Details and then Go on to the webpage:

Accept web browser security warning

Your secured IIS website is then displayed as in the following example:

View running secure IIS site

Next steps

In this tutorial, you secured an IIS web server with an SSL certificate stored in Azure Key Vault. You learned how to:

  • Create an Azure Key Vault
  • Generate or upload a certificate to the Key Vault
  • Create a VM and install the IIS web server
  • Inject the certificate into the VM and configure IIS with an SSL binding

Follow this link to see pre-built virtual machine script samples.