Skip to content

Subscription Provisioning

Every spoke needs a clean subscription. This page records the decision on how a platform gets that subscription: not from a pool, but created or prepared when the spoke is deployed. It explains the problem, the options that were considered, the consequences, and what this means for the MCP configuration.

Decision record

This is a design decision, written from an architecture decision record of the spoke canvas. It is guidance: your contract, your Azure agreement and your policies decide what you can do. See Design guidance.

The problem

Each spoke environment needs a clean subscription in which its resources and RBAC are set up. A pool of pre-created subscriptions looks attractive: a script claims one when a spoke is deployed. In practice it is risky, because spokes are deployed in parallel. Two spoke deployments can claim the same subscription.

Provisioning on demand also solves more than the claim problem:

  • no manual process is needed to fill up a pool,
  • no subscription exists without a purpose,
  • provisioning is more than creating the subscription. It also covers:
    • naming the subscription by convention when the spoke file gives no name,
    • setting the tags from the spoke file,
    • moving the subscription to the management group from the spoke file.

Options

Option Idea Why not, or why
Claim from a pool A pool of free subscriptions is ready. The deployment claims one Parallel deployments can claim the same subscription. Subscriptions in the pool need an import solution. A second solution must watch the pool and refill it
A provisioning step in the spoke deployment (chosen) The deployment detects, per spoke environment, whether a subscription is needed. If so, it creates it and passes the result on. Terraform then also sets name, management group and tags Fully automated. Compatible with existing spokes

Decision

Add a separate provisioning step to the spoke deployment that creates a subscription when needed, and let the same Terraform set the name, the management group association and the tags.

Consequences

  • Functionality is added without changing existing deployments. One new setting in the common spoke settings is needed to use it.
  • No pool has to be filled, monitored or cleaned up.
  • The step needs a billing relationship through which subscriptions can be created. That depends on your Azure agreement; see below.

How it maps to MCP

flowchart LR
    spoke["Spoke JSON file"] --> sub["Subscription layer<br/>deploy/subscription"]
    sub -->|"subscriptionId"| canvas["Spoke canvas layer<br/>deploy/spoke"]
    canvas --> r["Name, tags, management group,<br/>network, identity, resources"]

The spoke run has two Terraform layers with separate state (Provisioning). The subscription layer runs first and writes the subscription ID to a small output file. The spoke canvas layer reads that file (Spoke canvas module reference), moves the subscription to the management group, renames it and sets the tags.

Situation What happens
azureSubscriptionId is set in the spoke file The subscription is used as it is. This is how the pipelines are used today
azureSubscriptionId is empty and the CSP billing values are supplied The subscription layer can create the subscription

Creating subscriptions needs a billing route

Creating a subscription from code needs a billing account and a service principal with the rights to do so (the xmscsp_* inputs). The pipelines pass those inputs as empty strings. In a standard setup you create the subscription with your own EA, MCA or CSP process first, and put its ID in the spoke file (New spoke). Decide in your governance process who creates subscriptions.

If the pipeline cannot create subscriptions in your environment, the decision still holds in one respect: do not build a pool. Create a subscription per spoke request, and let the spoke deployment give it its name, tags and management group.