In this blog post, you’ll learn how to use an Azure PowerShell script to enable all Azure Bastion Standard SKU features with Azure PowerShell and with the REST API.
Nowadays, Azure Bastion, a Platform as a Service (PaaS) offering that ensures a secure connection to your Azure virtual machines (VMs) through RDP or SSH directly from the Azure portal over SSL, is available in Basic, Standard, and Developer SKUs (Tiers).
When using the Azure Bastion Standard SKU, you can choose to leverage the complete set of features Azure Bastion offers, including native client support, IP-based connection, and shareable link.
While deploying your standard SKU bastion host, upgrading from a Basic SKU bastion host, or incorporating them into your preferred deployment method, not all of these features are automatically activated. To enable them collectively, you can follow the steps detailed in this blog post using an Azure PowerShell script.
Table of Contents
- Prerequisites
- Executing actions and utilizing the Azure PowerShell script
- Azure PowerShell script
- Conclusion
Prerequisites
- An Azure subscription, preferably more than one, especially if you intend to align with the Cloud Adoption Framework (CAF) enterprise-scale architecture. This includes a connectivity and/or management subscription, along with landing zone subscriptions, depending on your specific needs and workloads.
- An Azure Administrator account with the required RBAC roles.
- An existing Azure Bastion host with the Standard SKU.
- The Azure Bastion host’s Public IP Address (PIP) must be located in the same resource group as your Azure Bastion host.
- At least Azure Az PowerShell module version 10.4.1 and Az.Network module version 6.2.0 are required.
Executing actions and utilizing the Azure PowerShell script
To automate the simultaneous enabling of all Azure Bastion Standard SKU features, I’ve created the following Azure PowerShell script, which does all of the following:
- Remove the breaking change warning messages.
- Change the current context to the subscription holding the Azure Bastion host, if the subscription exists; otherwise, exit the script..
- Save the Bastion host as a variable if it exists in the subscription and uses the Standard SKU; otherwise, exit the script.
- Store the current set of Azure Bastion host tags in a hash table.
- Enable the Azure Bastion Standard SKU features using the REST API.
To use the script, start by making a copy and saving it as “Enable-Azure-Bastion-Standard-SKU-features.ps1” or download it directly from GitHub. Then you can execute the script through Windows Terminal, Visual Studio Code, or Windows PowerShell. Alternatively, you have the option to run it directly from Cloud Shell.
Azure PowerShell script
If you are not running the script from Cloud Shell, remember to sign in with the Connect-AzAccount cmdlet to link your Azure account.
You can then run the script with the required parameters:
.\Enable-Azure-Bastion-Standard-SKU-features.ps1 <"your azure bastion host subscription name here"> <"your bastion host name here">
<#
.SYNOPSIS
A script used to enable all the Azure Bastion Standard SKU features (kerberos authentication, copy and paste, native client support, IP-based connection, and shareable link) on an Azure Bastion host.
.DESCRIPTION
A script used to enable all the Azure Bastion Standard SKU features (kerberos authentication, copy and paste, native client support, IP-based connection, and shareable link) on an Azure Bastion host.
The script will do all of the following:
Remove the breaking change warning messages.
Change the current context to the subscription holding the Azure Bastion host, if the subscription exists; otherwise, exit the script.
Save the Bastion host as a variable if it exists in the subscription and uses the Standard SKU; otherwise, exit the script.
Store the current set of Azure Bastion host tags in a hash table.
Enable the Azure Bastion Standard SKU features using the REST API.
.NOTES
Filename: Enable-Azure-Bastion-Standard-SKU-features.ps1
Created: 02/12/2023
Last modified: 02/12/2023
Author: Wim Matthyssen
Version: 1.0
PowerShell: Azure PowerShell and Azure Cloud Shell
Requires: PowerShell Az (v10.4.1)
Action: Change variables were needed to fit your needs.
Disclaimer: This script is provided "as is" with no warranties.
.EXAMPLE
Connect-AzAccount
Get-AzTenant (if not using the default tenant)
Set-AzContext -tenantID "xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx" (if not using the default tenant)
.\Enable-Azure-Bastion-Standard-SKU-features.ps1 <"your azure bastion host subscription name here"> <"your bastion host name here">
-> .\Enable-Azure-Bastion-Standard-SKU-features.ps1 sub-hub-myh-management-01 bas-hub-myh-01
.LINK
https://wmatthyssen.com/2023/12/04/azure-bastion-enable-azure-bastion-standard-sku-features-with-azure-powershell/
#>
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Parameters
param(
# $subscriptionName -> Name of the subscription holding the Azure Bastion host
[parameter(Mandatory =$true)][ValidateNotNullOrEmpty()] [string] $subscriptionName,
# $bastionName -> Name of the Azure Bastion host
[parameter(Mandatory =$true)][ValidateNotNullOrEmpty()] [string] $bastionName
)
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Variables
$httpsUriStart = "https://management.azure.com/subscriptions/"
$createApiVersion = "?api-version=2022-07-01"
$authenticationType = "Bearer"
$method = "Put"
$contentType = "application/json"
$bastionSubnetName = "AzureBastionSubnet"
# Time, colors, and formatting
Set-PSBreakpoint -Variable currenttime -Mode Read -Action {$global:currenttime = Get-Date -Format "dddd MM/dd/yyyy HH:mm"} | Out-Null
$foregroundColor1 = "Green"
$foregroundColor2 = "Yellow"
$writeEmptyLine = "`n"
$writeSeperatorSpaces = " - "
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Remove the breaking change warning messages
Set-Item -Path Env:\SuppressAzurePowerShellBreakingChangeWarnings -Value $true | Out-Null
Update-AzConfig -DisplayBreakingChangeWarning $false | Out-Null
$warningPreference = "SilentlyContinue"
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Write script started
Write-Host ($writeEmptyLine + "# Script started. Without errors, it takes up to 1 minute to complete" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Change the current context to the subscription holding the Azure Bastion host, if the subscription exists; otherwise, exit the script
Get-AzSubscription -SubscriptionName $subscriptionName -ErrorVariable subscriptionNotPresent -ErrorAction SilentlyContinue | Out-Null
if ($subscriptionNotPresent) {
Write-Host ($writeEmptyLine + "# Subscription with name $subscriptionName does not exist in the current tenant" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor3 $writeEmptyLine
Start-Sleep -s 3
Write-Host -NoNewLine ("# Press any key to exit the script ..." + $writeEmptyLine)`
-foregroundcolor $foregroundColor1 $writeEmptyLine;
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null;
return
} else {
Set-AzContext -Subscription $subscriptionName | Out-Null
Write-Host ($writeEmptyLine + "# Subscription with name $subscriptionName in current tenant selected" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
}
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Save the Bastion host as a variable if it exists in the subscription and uses the Standard SKU; otherwise, exit the script
$bastionObject = Get-AzBastion | Where-Object Name -Match $bastionName
$bastionName = ($bastionObject).Name
if ($null -eq $bastionObject){
Write-Host ($writeEmptyLine + "# There is no Bastion host included in the current subscription" + $writeSeperatorSpaces + $currentTime) -foregroundcolor $foregroundColor2 $writeEmptyLine
Start-Sleep -s 3
Write-Host ($writeEmptyLine + "# Press any key to exit the script ..." + $writeEmptyLine) -foregroundcolor $foregroundColor1 $writeEmptyLine
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null;
return
} else {
if ($bastionObject.SkuText.Contains("Basic")) {
Write-Host ($writeEmptyLine + "# Bastion host runs with the Basic SKU, please upgrade to Standard SKU" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor3 $writeEmptyLine
Start-Sleep -s 3
Write-Host ($writeEmptyLine + "# Press any key to exit the script ..." + $writeEmptyLine)`
-foregroundcolor $foregroundColor1 $writeEmptyLine;
$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null;
return
} else {
Write-Host ($writeEmptyLine + "# Bastion host $bastionName exists in the current subscription and uses the Standard SKU; the script will continue" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
}
}
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Store the current set of Azure Bastion host tags in a hash table
$bastionResourceGroupName = $bastionObject.ResourceGroupName
$bastionTags = (Get-AzResource -ResourceGroupName $bastionResourceGroupName -ResourceName $bastionName).Tags
Write-Host ($writeEmptyLine + "# Specified set of tags available to add" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Enable the Azure Bastion Standard SKU features using the REST API
# Get subscription ID
$subscriptionID = (Get-AzContext).Subscription.Id
# Get Bastion location
$bastionLocation = $bastionObject.Location
# Get Bastion Public IP Address (PIP)
$publicip = Get-AzPublicIpAddress -ResourceGroupName $bastionResourceGroupName
# Get AzureBastionSubnet
$bastionSubnet = Get-AzVirtualNetwork | Where-Object { $_.Subnets -ne $null -and $_.Subnets.Name -contains $bastionSubnetName } | Get-AzVirtualNetworkSubnetConfig -Name $bastionSubnetName
# Create REST API parameters
$uri = $httpsUriStart + $subscriptionID + "/resourceGroups/$($bastionResourceGroupName)/providers/Microsoft.Network/bastionHosts/$bastionName/$createApiVersion"
$token = (Get-AzAccessToken).Token | ConvertTo-SecureString -AsPlainText -Force
$body = @{
location = $bastionLocation
tags = $bastionTags
properties = @{
disableCopyPaste = $false
enableKerberos = $true #also requires setting the DNS settings of your VNet to your Azure-hosted domain controller(s)
enableTunneling = $true
enableIpConnect = $true
enableShareableLink = $true
ipConfigurations = @(@{name = "bastionHostIpConfiguration"; properties = @{subnet = @{id = $bastionSubnet.id}; publicIPAddress = @{id = $publicip.Id}}})
}
} | ConvertTo-Json -Depth 6
# Send an HTTP or HTTPS request to a REST API endpoint
Invoke-WebRequest -Uri $uri -Authentication $authenticationType -Token $token -Method $method -Body $body -ContentType $contentType | Out-Null
Write-Host ($writeEmptyLine + "# The Azure Bastion Standard SKU features are enabled for bastion host $bastionName" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Write script completed
Write-Host ($writeEmptyLine + "# Script completed; keep in mind that it can take up to 6 minutes before all features are fully usable" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine
## ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Conclusion
When utilizing the Azure Bastion Standard SKU, you have the option to unlock the full suite of features it offers, such as native client support, IP-based connection, and shareable links. However, these features aren’t always activated by default.
So, I hope that the Azure PowerShell script shared in this blog post will be useful for you, simplifying the enabling of all these features or the Bastion host using the Standard SKU within your environment.
Should you have any questions or suggestions regarding this script, feel free to reach out to me through my X handle (@wmatthyssen) or drop a comment. I’ll be more than happy to assist you.
Pingback: Azure Bastion: Enable Azure Bastion Standard SKU features with Azure PowerShell – Stack IT News