Azure Azure Bastion Azure PowerShell

Azure Bastion: Enable Azure Bastion Standard SKU features with Azure PowerShell


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

  • 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.



Wim is an Azure Technical Advisor and Trainer with over fifteen years of Microsoft technology experience. As a Microsoft Certified Trainer (MCT), his strength is assisting companies in the transformation of their businesses to the Cloud by implementing the latest features, services, and solutions. Currently, his main focus is on the Microsoft Hybrid Cloud Platform, and especially on Microsoft Azure and the Azure hybrid services.   Wim is also a Microsoft MVP in the Azure category and a founding board member of the MC2MC user group. As a passionate community member, he regularly writes blogs and speaks about his daily experiences with Azure and other Microsoft technologies.

1 comment on “Azure Bastion: Enable Azure Bastion Standard SKU features with Azure PowerShell

  1. Pingback: Azure Bastion: Enable Azure Bastion Standard SKU features with Azure PowerShell – Stack IT News

Leave a comment