Setting up WinRM access for Virtual Machines in Azure Resource Manager
Applies to: ✔️ Windows VMs ✔️ Flexible scale sets
Here are the steps you need to take to set up a VM with WinRM connectivity
- Create a Key Vault
- Create a self-signed certificate
- Upload your self-signed certificate to Key Vault
- Get the URL for your self-signed certificate in the Key Vault
- Reference your self-signed certificates URL while creating a VM
Step 1: Create a Key Vault
You can use the below command to create the Key Vault
New-AzKeyVault -VaultName "<vault-name>" -ResourceGroupName "<rg-name>" -Location "<vault-location>" -EnabledForDeployment -EnabledForTemplateDeployment
Step 2: Create a self-signed certificate
You can create a self-signed certificate using this PowerShell script
$certificateName = "somename"
$thumbprint = (New-SelfSignedCertificate -DnsName $certificateName -CertStoreLocation Cert:\CurrentUser\My -KeySpec KeyExchange).Thumbprint
$cert = (Get-ChildItem -Path cert:\CurrentUser\My\$thumbprint)
$password = Read-Host -Prompt "Please enter the certificate password." -AsSecureString
Export-PfxCertificate -Cert $cert -FilePath ".\$certificateName.pfx" -Password $password
Step 3: Upload your self-signed certificate to the Key Vault
Before uploading the certificate to the Key Vault created in step 1, it needs to be converted into a format the Microsoft.Compute resource provider will understand. The below PowerShell script will allow you to do that
$fileName = "<Path to the .pfx file>"
$fileContentBytes = Get-Content $fileName -Encoding Byte
$fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes)
[System.Collections.HashTable]$TableForJSON = @{
"data" = $fileContentEncoded;
"dataType" = "pfx";
"password" = "<password>";
}
[System.String]$jsonObject = $TableForJSON | ConvertTo-Json
$encoding = [System.Text.Encoding]::UTF8
$jsonEncoded = [System.Convert]::ToBase64String($encoding.GetBytes($jsonObject))
$secret = ConvertTo-SecureString -String $jsonEncoded -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName "<vault name>" -Name "<secret name>" -SecretValue $secret
Step 4: Get the URL for your self-signed certificate in the Key Vault
The Microsoft.Compute resource provider needs a URL to the secret inside the Key Vault while provisioning the VM. This enables the Microsoft.Compute resource provider to download the secret and create the equivalent certificate on the VM.
Note
The URL of the secret needs to include the version as well. An example URL looks like below https://contosovault.vault.azure.cn:443/secrets/contososecret/01h9db0df2cd4300a20ence585a6s7ve
Templates
You can get the link to the URL in the template using the below code
"certificateUrl": "[reference(resourceId(resourceGroup().name, 'Microsoft.KeyVault/vaults/secrets', '<vault-name>', '<secret-name>'), '2015-06-01').secretUriWithVersion]"
PowerShell
You can get this URL using the below PowerShell command
$secretURL = (Get-AzKeyVaultSecret -VaultName "<vault name>" -Name "<secret name>").Id
Step 5: Reference your self-signed certificates URL while creating a VM
Azure Resource Manager Templates
While creating a VM through templates, the certificate gets referenced in the secrets section and the winRM section as below:
"osProfile": {
...
"secrets": [
{
"sourceVault": {
"id": "<resource id of the Key Vault containing the secret>"
},
"vaultCertificates": [
{
"certificateUrl": "<URL for the certificate you got in Step 4>",
"certificateStore": "<Name of the certificate store on the VM>"
}
]
}
],
"windowsConfiguration": {
...
"winRM": {
"listeners": [
{
"protocol": "http"
},
{
"protocol": "https",
"certificateUrl": "<URL for the certificate you got in Step 4>"
}
]
},
...
}
},
A sample template for the above can be found here at vm-winrm-keyvault-windows
Source code for this template can be found on GitHub
PowerShell
$vm = New-AzVMConfig -VMName "<VM name>" -VMSize "<VM Size>"
$credential = Get-Credential
$secretURL = (Get-AzKeyVaultSecret -VaultName "<vault name>" -Name "<secret name>").Id
$vm = Set-AzVMOperatingSystem -VM $vm -Windows -ComputerName "<Computer Name>" -Credential $credential -WinRMHttp -WinRMHttps -ProvisionVMAgent -WinRMCertificateUrl $secretURL
$sourceVaultId = (Get-AzKeyVault -ResourceGroupName "<Resource Group name>" -VaultName "<Vault Name>").ResourceId
$CertificateStore = "My"
$vm = Add-AzVMSecret -VM $vm -SourceVaultId $sourceVaultId -CertificateStore $CertificateStore -CertificateUrl $secretURL
Step 6: Connecting to the VM
Before you can connect to the VM, you'll need to make sure your machine is configured for WinRM remote management. Start PowerShell as an administrator and execute the below command to make sure you're set up.
Enable-PSRemoting -Force
Note
You might need to make sure the WinRM service is running if the above does not work. You can do that using Get-Service WinRM
Once the setup is done, you can connect to the VM using the below command
Enter-PSSession -ConnectionUri https://<public-ip-dns-of-the-vm>:5986 -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck) -Authentication Negotiate