Most secure way to access Azure Cloud

What if I told you that you could access your Azure Cloud Resources and tick the following boxes:

  • More secure than a VPN
  • More secure than a Bastion Host and Jumpbox
  • No need for patching and SOC2 compliance reports

If your cloud environment is serverless, why settle for less when it comes to remote access?

As soon as you introduce a jump box, you are required to patch the damn thing and this eats into the Opex budget in a big way.

So what is the solution?

What if you had a docker image with all the tools you need for support that you can spin up into an Azure Container Instance and access on demand, with the filesystem running off Azure Blob Storage?

Well, this is possible, and the good news is that you do not need to build it yourself. Microsoft already offers it.

Welcome to Azure Cloud Shell with VNET Integration!

Cloud Shell with VNET integration leveraging subnet delegation for ACI

The only limitation is that the Storage Account only supports Primary Regions, however Microsoft notified me today that Australia East is now supported.

Microsoft is currently working on more secondary region support, just something to be aware of from a security/data sovereignty perspective.

So the experience is like this.

  1. Log into the Azure Portal
  2. Choose Cloud Shell with advanced options – Select VNET Integration and select the subnet / storage account that we will terraform
  3. Boom – You are in the Azure network and Cloud Shell will have all your common support tools that your require.


We will need:

  • Dedicated subnet for CloudShell ACI instances to spin up in.

"csh" = ""

  • Dedicated support subnet for storage account

"sup" = ""

  • A dedicate subnet for the Azure Relay
relay_subnet = ""

# Container instance built in OID for permissions / delegation
# Manually grant in Azure AD
container_instance_oid = "4c1b7058-e8ea-4854-abd2-bbb0abb6cd24"
  • Storage Account for OS filesystem – network rules for Cloudshell
# See
resource "azurerm_storage_account" "cloud_shell" {
  name                         = "st${var.client}${var.env}${var.location_shortname}sup"
  resource_group_name          =
  location                     = azurerm_resource_group.rg.location
  allow_blob_public_access     = false
  account_tier                 = "Standard"
  access_tier                  = "Cool"
  account_replication_type     = "LRS"
  tags                         = local.tags
  enable_https_traffic_only    = true
  network_rules {
    bypass                     = ["None"]
    default_action             = "Deny"
    ip_rules                   = [ "" ]
    virtual_network_subnet_ids = [,

resource "azurerm_storage_share" "cloud_shell" {
  name                 = "cshsupport"
  storage_account_name =
  quota                = 50
  • Then a Cloudshell Subnet leveraging subnet delegation so ACI can control network devices
resource "azurerm_subnet" "cloud_shell_subnet" {
  name                 = "snet-${local.resource_id}-${var.client}-csh"
  resource_group_name  =
  virtual_network_name =
  address_prefixes     = [var.cloud_shell_subnet]

  delegation {
    name = "delegation"

    service_delegation {
      name    = "Microsoft.ContainerInstance/containerGroups"
  service_endpoints = [
  • Azure Relay Subnet and setup
resource "azurerm_subnet" "relay_subnet" {
  name                                            = "snet-${local.resource_id}-${var.client}-rel"
  resource_group_name                             =
  virtual_network_name                            =
  address_prefixes                                = [var.relay_subnet]
  enforce_private_link_endpoint_network_policies  = true
  enforce_private_link_service_network_policies   = false

resource "azurerm_relay_namespace" "relay_namespace" {
  name                = "rel-${local.resource_id}-${var.client}-csh"
  location            = azurerm_resource_group.rg.location
  resource_group_name =
  sku_name = "Standard"
  tags = local.tags

resource "azurerm_network_profile" "cloud_shell_containers" {
  name                = "netpr-${local.resource_id}-${var.client}-csh"
  location            = azurerm_resource_group.rg.location
  resource_group_name =
  tags = local.tags
  container_network_interface {
    name = "eth-${}"

    ip_configuration {
      name      = "ipconfig-${}"
      subnet_id =

resource "azurerm_private_endpoint" "relay_csh" {
  name                = "prve-${local.resource_id}-${var.client}-csh"
  location            = azurerm_resource_group.rg.location
  resource_group_name =
  tags                = local.tags

  subnet_id           =
  private_service_connection {
    name                           = "prvsc-${local.resource_id}-${var.client}-csh"
    private_connection_resource_id =
    subresource_names              = ["namespace"]
    is_manual_connection           = false

resource "azurerm_private_dns_zone" "private_dns_relay" {
  name                = ""
  resource_group_name =
  tags                = local.tags

resource "azurerm_private_dns_a_record" "relay_dns_a_record" {
  name                = "csh"
  zone_name           =
  resource_group_name =
  ttl                 = 3600
  records             = [azurerm_private_endpoint.relay_csh.private_service_connection[0].private_ip_address]

resource "azurerm_private_dns_zone_virtual_network_link" "relay_vnet_link" {
  name                  = "dnsvl-${local.resource_id}-${var.client}-csh"
  resource_group_name   =
  private_dns_zone_name =
  virtual_network_id    =
  registration_enabled  = false

Now connect to CloudShell

So the above should get you on the right track for the most secure and painless free maintenance Remote Access solution for Azure Cloud!

Goodbye VPN!
Goodbye Bastion Host!
Goodbye Jumpboxes!

CloudShell Vnet


  • Uncategorized

Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s