Let’s Explore: Azure Bastion

2019/06/29

Consumers of commercial cloud Infrastructure-as-a-Service solutions need methods to manage their cloud-based assets. One method employs Bastion Hosts - secure jump boxes that provide remote access to your environment while limiting attack surface. I’ve typically employed a Linux VM for this task, hardened and configured for the single purpose of accessing the environment via ssh. Azure now has in preview the Azure Bastion. It is positioned as a Platform-as-a-Service (PaaS) resource for securely accessing virtual machines in your Azure environment. Let’s take a look at deployment and usage of Azure Bastion (preview) and compare to roll-your-own Linux server bastion hosts.

This article covers my initial impressions of Azure Bastion following a simple deployment and running through some routine tasks I perform daily. I won’t cover detailed steps for creating a Bastion resource. Links to Microsoft Docs will provide sufficient guidance for deploying and using this preview resource. Where applicable I will provide insights I felt significant from my experience, such as gaps in documentation or items of note that I encountered.

Note that as of this writing Azure Bastion is in public preview, meaning it is still under development and not intended for production use. The final version may look and operate slightly different than the preview version. In fairness I’ve tried to emphasize this point several times throughout this document, especially when identifying things I didn’t like or thought could be better. This document may become irrelevant following general release of Azure Bastion.

Prepare Your VNet

At the time of this writing, the Azure Bastion preview feature was only available in the following regions:

Prior to creating the Bastion resource, ensure your VNet contains a subnet named AzureBastionSubnet with a prefix of at least /27. Name the subnet exactly as directed. The subnet should be of normal type, not a gateway subnet. Azure prevents creation of other resources in this subnet.

Registering for Azure Bastion Preview - Azure CLI

The preview documentation walks through registration using PowerShell, but you can register using the Azure CLI as well. Use the feature and provider subgroups as shown below.

ed@block:~$ az feature register --namespace Microsoft.Network -n AllowBastionHost
Once the feature 'AllowBastionHost' is registered, invoking 'az provider register -n Microsoft.Network' is required to get the change propagated
{
    "id": "/subscriptions/{{OMITTED}}/providers/Microsoft.Features/providers/Microsoft.Network/features/AllowBastionHost",
    "name": "Microsoft.Network/AllowBastionHost",
    "properties": {
        "state": "Registering"
    },
    "type": "Microsoft.Features/providers/features"
}
ed@block:~$ az provider register -n Microsoft.Network
ed@block:~$
ed@block:~$ az feature show --namespace Microsoft.Network -n AllowBastionHost
{
    "id": "/subscriptions/{{OMITTED}}/providers/Microsoft.Features/providers/Microsoft.Network/features/AllowBastionHost",
    "name": "Microsoft.Network/AllowBastionHost",
    "properties":
    {
        "state": "Registering"
    },
    "type": "Microsoft.Features/providers/features"
}
ed@block:~$

After a few minutes the feature will show as successfully registered.

ed@block:~$ az feature show --namespace Microsoft.Network -n AllowBastionHost
{
    "id": "/subscriptions/{{OMITTED}}/providers/Microsoft.Features/providers/Microsoft.Network/features/AllowBastionHost",
    "name": "Microsoft.Network/AllowBastionHost",
    "properties":
    {
        "state": "Registered"
    },
    "type": "Microsoft.Features/providers/features"
}
ed@block:~$

Once the feature has been registered you can proceed to the Preview Portal to create the Bastion resource. Note this cannot be done in your regular portal, so follow the link in the document for the Preview Portal.

While waiting for the  feature to register I viewed the Activity Log output to monitor messages. The fact that the activity log showed the Register Subscription status as Successful while the Azure CLI output of az feature show --namespace Microsoft.Network -n AllowBastionHost still showed Registering confused me. Its likely that I misunderstood the Activity Log output, as it probably denotes the status of the API command acceptance rather than the actual operation.

Interestingly, the Azure Bastion did not appear as a dynamic result while typing into the search field (only WALLIX Bastion). Executing and viewing full search results revealed the Azure Bastion option.

Deployment time of the Bastion was approximately 10 minutes. Fortunately this is not as long as some other resources, such as VPN gateways or App gateways, and the deployment time may be reduced when the feature enters general availability. Your resource list now contains a new object of type Bastion.

The Bastion Resource

The Bastion resource appears in your All Resources list, and is also referenced when viewing the Virtual Network. Two Scale Set instances appear with their IP addresses in the AzureBastionSubnet. Attempting to access these resources (clicking on them in the Portal) results in an Access Denied error. Other than these appearances I did not see the Bastion devices in other areas - they are not listed in the VM Scale Set or Virtual Machines blades.

Once deployed there appear to be no configurable items on the Bastion resource. I was unable to find a way to disable or deallocate the Bastion resource so the only apparent way to stop spend is to delete the Bastion and it’s associated Public IP. While fine for an enterprise production network, this limits usefulness in my personal pay-as-you-go (PAYG) subscription where extraneous costs must be minimized. Understandably my personal lab subscription does not constitute a significant share of Azure revenue so I can be content in deallocating and re-deploying the resource via template if required. The Bastion resource blade contains a section for Metrics though there (currently) are no metrics for the resource itself. Standard metrics are available for the Public IP attached to the Bastion.

Though the Bastion deploys with a Public IP, it did not appear to be used. When accessing a virtual machine through the Bastion, the resulting URL resolved to a different Azure Public IP. I thought the Public IP deployed with the Bastion was to be used for the HTTPS session to the bastion that displays the target VM’s RDP or SSH session. Maybe this is still being worked on the back-end, and Azure currently ‘shares’ a limited number of Bastion assets across preview subscribers?

Using the Bastion

The Portal now displays a Bastion option under the Connect button on the VM Overview. The user completes sections of the form to specify the OS user as well as whether a password or ssh key should be used to connect. The ssh key can be pasted into the browser window or selected from file on the local workstation. The Advanced tab allows entering the passphrase to unlock the private RSA key, if encrypted. Note that the passphrase is not hidden or obfuscated like a secure string, so it will be visible on-screen! If you omit the passphrase here, you will be prompted to enter the passphrase in the ssh console window (a new browser session) that opens, and the passphrase is not echoed back in this window. My initial connection tests to a Linux machine showed that Bastion was opening two ssh sessions to the machine, though one would close after a while. I’m not sure why this was done, perhaps one was a fleeting health check I happened to capture when viewing active connections.

The one test Windows machine I used only allowed username and password for access. I suspect additional authentication methods will be available later after preview, as smart card authentication would be good. If you’re accessing the Bastion solely via Portal perhaps your Azure Active Directory accounts are already MFA protected, whether via federation or using methods natively available in AAD. That may mitigate the need for 2FA access to console sessions. I was able to log into the same Windows machine with two Bastion sessions from the same AAD user, but my Windows user was booted from one session because I used the same Windows account. Regardless it looks like you can have multiple Bastion sessions open to the same VM simultaneously.

The Bastion opens the ssh or RDP session in a new browser window. I suspect this works with any modern OS and browser since it is based on HTML5. Responsiveness was about what I’d expect for a remote session. Ssh terminal sessions are always pretty snappy, and RDP was pretty good as well. Any lag in my RDP session was likely more due to the small test server instance I provisioned.

The Bastion screen provides a small fly-out window that opens a clipboard window. Text copied in the ssh/RDP session is available in this window for copying to the local workstation.

Overall Impressions

Bastion provides a basic, easy-to-use interface for connecting to VMs from the portal. Accessing in this manner restricts connections to only those authorized permissions in the portal, and security is as strong as your portal identities. I’m basing this on the assumption that any future use of the Public IP deployed with Bastion is for connecting through the Bastion to back-end resources, and any possible ‘direct’ access to this IP also requires authentication through AAD. One additional benefit of this would be the ability to restrict connections to the Bastion from source IP ranges via a Network Security Group. At present I couldn’t see the use of the Public IP deployed with the Bastion - perhaps it performs a function I couldn’t see or is a future implementation.

A few pros and cons based on my typical usage:

Pros:

Cons:

Additional Information

Documentation:

Pricing: