Blog Post

Azure Governance and Management Blog
6 MIN READ

Subscription Vending, now and beyond

Seif_Bassem's avatar
Seif_Bassem
Icon for Microsoft rankMicrosoft
Mar 19, 2025

Why do you need a Subscription Vending process?

As organizations expand their cloud presence, efficiently provisioning and managing Azure subscriptions becomes a critical challenge. Traditionally, subscription creation has been a manual, time-consuming process that slows down application teams and increases operational complexity for platform teams. To address this, subscription vending automates and standardizes subscription provisioning, making it easier for teams to deploy workloads while ensuring governance and compliance. Instead of relying on manual requests and approvals, it standardizes and accelerates the process, ensuring governance while giving teams faster access to the cloud environments they need.

A key principle behind this approach is subscription democratization, one of the core design principles of Azure landing zones. Rather than relying on resource groups as the primary unit of management, subscription democratization treats subscriptions as the fundamental building blocks for scaling workloads. This separation allows organizations to better enforce governance, manage cost boundaries, and apply policies at scale, aligning with best practices for enterprise-scale cloud adoption.

Subscription vending modules can be used with or without an Azure platform landing zone. 

With subscription vending, organizations can:

  • Streamline provisioning – Provide a structured and automated way to create and configure new subscriptions.
  • Enforce governance – Ensure compliance with security, networking, and cost management policies from the start.
  • Boost agility – Enable application teams to quickly deploy workloads without waiting for complex approvals.

By integrating the subscription vending infrastructure-as-code (IaC) modules (Bicep or Terraform), subscription management becomes more scalable, secure, and efficient.

What are some of the use cases Subscription Vending addresses?

  • Provision a new subscription or configure an existing one
  • Deploy Tags
  • Move to a certain management group
  • Provision role assignments
  • Deploy a virtual network
  • Assign a DDOS plan to the virtual network
  • Configure peering with hub (whether it's a hub-and-spoke or virtual wan topology)

What's new?

Since we released the Bicep and Terraform subscription vending modules, we have been improving them and adding more features to make it even more seamless to provision and manage subscriptions at scale. Let's explore what has changed so far specifically in the Bicep module:

Enter "Azure Verified Modules"

The Bicep subscription vending module has been migrated to be Azure Verified Modules (AVM), that means it is hosted in the public Bicep registry, which help us align with the Well-architected framework guidance, improve module support, easier upgrades and release tracking and provide you with a consistent experience consuming AVM modules. 

Subscription preparation

You can now as part of the subscription provisioning automatically register the most common resource providers or select specific ones to make it easier for the application teams to quickly and successfully deploy their Azure services and avoid deployment failures due to unregistered providers/features. You can also specify preview features to be registered if needed. This is done using a deployment script after the subscription has been provisioned.

targetScope = 'managementGroup'

@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    resourceProviders: {
      'Microsoft.HybridCompute': ['ArcServerPrivateLinkPreview']
      'Microsoft.AVS': ['AzureServicesVm']
      'Microsoft.Network': []
    }
  }
}

RBAC constrained delegation

You can now increase the controls on RBAC role assignments you assign as part of subscription vending by including conditions. The module makes it very easy to specify the condition you need without having to write down the condition expression.

targetScope = 'managementGroup'

@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    roleAssignments: [
      {
        principalId: 'XXXXX-XXXXX-XXXXXX-XXXXXX'
        definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168'
        relativeScope: ''
        principalType: 'User'
        roleAssignmentCondition: {
          roleConditionType: {
            principleTypesToAssign: [
              'Group'
              'User'
            ]
            rolesToAssign: [
              'b24988ac-6180-42a0-ab88-20f7382dd24c'
            ]
            templateName: 'constrainRolesAndPrincipalTypes'
          }
        }
      }
    ]
  }
}

Govern privileged roles with Privileged Identity Management (PIM)

As part of the module, in addition to managing role assignments, you can now create PIM role assignments to govern privileged roles like Owner and User Access Administrator. You can assign those roles as eligible or active with duration.

targetScope = 'managementGroup'
@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

@description('Optional. The start time of the the PIM role assignment.')
param pimAssignmentStartDateTime string = utcNow()

@description('Required. Principle ID of the user.')
param testUserObjectId string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    pimRoleAssignments: [
      {
        principalId: testUserObjectId
        relativeScope: ''
        roleAssignmentType: 'Eligible'
        definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168'
        scheduleInfo: {
          duration: 'PT4H'
          durationType: 'AfterDuration'
          startTime: pimAssignmentStartDateTime
        }
        justification: 'This is a justification for assigning this role.'
      }
      {
        principalId: testUserObjectId
        relativeScope: '/resourceGroups/rsg-hr-phoenix'
        roleAssignmentType: 'Active'
        definition: '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168'
        scheduleInfo: {
          duration: 'PT4H'
          durationType: 'AfterDuration'
          startTime: pimAssignmentStartDateTime
        }
        justification: 'This is a justification for assigning this role.'
      }
    ]
  }
}

Virtual network subnets creation

The module now allows you to not only create a virtual network in the new subscription but also define the subnets to be created.

targetScope = 'managementGroup'

@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    virtualNetworkEnabled: true
    virtualNetworkName: 'vnet-hr-phoenix'
    virtualNetworkResourceGroupName: 'rg-hr-phoenix'
    virtualNetworkAddressSpace: [
      '10.0.0.0/16'
    ]
    virtualNetworkLocation: 'eastus'
    virtualNetworkSubnets: [
      {
        name: 'subnet-vms'
        addressPrefix: '10.0.1.0/24'
        delegation: 'Microsoft.Sql/managedInstances'
      }
    ]
  }
}

Secure outbound virtual machine internet access via a NAT gateway

On 30 September 2025, default outbound access connectivity for virtual machines in Azure will be retired, and one of the recommended options is to leverage a NAT gateway to provide outbound internet access to your virtual machines. You can now deploy one and associate with subnets in the newly created subscription.

targetScope = 'managementGroup'

@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    virtualNetworkEnabled: true
    virtualNetworkName: 'vnet-hr-phoenix'
    virtualNetworkResourceGroupName: 'rg-hr-phoenix'
    virtualNetworkAddressSpace: [
      '10.0.0.0/16'
    ]
    virtualNetworkLocation: 'eastus'
    virtualNetworkSubnets: [
      {
        name: 'subnet-vms'
        addressPrefix: '10.0.1.0/24'
        delegation: 'Microsoft.Sql/managedInstances'
        associateWithNatGateway: true
      }
    ]
    virtualNetworkDeployNatGateway: true
    virtualNetworkNatGatewayConfiguration: {
      name: 'natgw-hr-phoenix'
      publicIPAddressProperties: [
        {
          name: 'pip-natgw-hr-phoenix'
          zones: [
            1
            2
            3
          ]
        }
      ]
    }
  }
}

Secure remote connection to virtual machines via Azure Bastion

There are two approaches to deploy Azure Bastion in large deployments:

  • Centralized: where there is one host deployed in the hub network and all teams use it to securely connect to their landing zones and workloads
  • Decentralized: each team get their own Bastion host deployed into their landing zone, giving more flexibility in-terms of selecting the SKU and features they require and control costs.

The module allows for deploying Bastion in a decentralized manner into the newly created subscription.

targetScope = 'managementGroup'

@description('Required. The scope of the subscription billing.')
param subscriptionBillingScope string = ''

module subscriptionVending 'br:mcr.microsoft.com/bicep/avm/ptn/lz/sub-vending:0.3.0' = {
  name: 'subscriptionVending'
  params: {
    subscriptionAliasEnabled: true
    subscriptionBillingScope: subscriptionBillingScope
    subscriptionAliasName: 'dep-sub-hr-phoenix'
    subscriptionDisplayName: 'dep-sub-hr-phoenix'
    subscriptionWorkload: 'Production'
    subscriptionTags: {
      workload: 'phoenix'
      department: 'hr'
    }
    virtualNetworkEnabled: true
    virtualNetworkName: 'vnet-hr-phoenix'
    virtualNetworkResourceGroupName: 'rg-hr-phoenix'
    virtualNetworkAddressSpace: ['10.0.0.0/16']
    virtualNetworkLocation: 'eastus'
    virtualNetworkSubnets: [
      {
        name: 'Subnet1'
        addressPrefix: '10.130.1.0/24'
      }
      {
        name: 'AzureBastionSubnet'
        addressPrefix: '10.130.0.0/26'
      }
    ]
    virtualNetworkDeployBastion: true
    virtualNetworkBastionConfiguration: {
      bastionSku: 'Premium'
      name: 'bastion-hr-phoenix'
      enableFileCopy: true
      enableIpConnect: true
      enablePrivateOnlyBastion: false
    }
  }
}

Subscription Vending future

We plan to bring more capabilities to the Bicep and Terraform modules to provide a more automated and streamlined application landing zone deployment and to extend the bootstrapping process to GitHub and Azure DevOps repositories.

Resources 

Updated Mar 19, 2025
Version 1.0

2 Comments

  • From the operational standpoint, which is better that the Azure Administrators vend subscription these bicep modules or let users deploy by themselves with these bicep?

    • Seif_Bassem's avatar
      Seif_Bassem
      Icon for Microsoft rankMicrosoft

      Its usually the Cloud excellence/Platform/Admin team that creates an automated process where application owners submit their requests and that triggers the sub-vending modules. We see customers integrate it usually with their existing service management systems