Skip to content

Change a Spoke

Standard change: Changes to spoke canvas. This covers the RBAC owner, service principal information, networking, and so on.

Effect: Terraform reconciles the existing spoke with its edited JSON file. Only the differences are applied.

Request fields

Same as New spoke: Name, Rationale, Environment, Usage type, Exposure to public internet, IP range/size, subnet name/size/delegations/service endpoints, which team needs access, and Comments. Fill in only the fields that change.

How it works

There is no separate "update" pipeline. You edit the spoke's JSON file and run spoke for that file. The spoke keeps its identity through its Terraform state key, spoke_<workloadShortName>_<environment>.tfstate. So:

Never change workloadShortName or environment of an existing spoke. Either change creates a new state key and a full second spoke, while the old one stays as it is. Renaming the file or moving it to another folder is safe: the file name is only used for job and artifact names.

What you can change, and what happens

Change JSON field What the plan should show
Add a subnet append to network[].subnets[] subnet created + NSG association (+ route table association)
Change subnet delegations or service endpoints subnets[].delegations / .serviceEndpoints subnet updated
Change a subnet or VNet address range subnets[].addressPrefix, network[].addressPrefix Update or replace. Azure refuses to resize a subnet that has resources in it. If the plan says must be replaced, stop and plan a migration.
Add or change NSG rules networksecuritygroups[].rules[] rules created or updated. Don't change the priority of an existing rule: the rule is recreated, and that can fail and leave the NSG inconsistent. Add a new rule with a new name and a new priority, then remove the old rule in a later change.
Add a route table / routes routetables[], and subnets[].linkedroutetablename route table + association
Grant another team access append to adInfo.ProductTeamGroupNames PIM eligibility or active membership for the new group
Change PIM behavior adInfo.PIMGroupConfig.{Readers,Contributors,Owners} PIM settings updated
Change who can use a data-plane role (Key Vault, Storage, others) adInfo.PIMAssignments Role assignments and PIM eligibility at subscription scope. See RBAC and PIM.
Add an Azure DevOps repository and service connection azdo New repo and service connection. Prepare first: Spoke integrations.
Add a GitHub repository with federated credentials extensions.github New repo, federated credentials, Actions secrets. See Spoke integrations.
Add an environment to the GitHub federated credentials extensions.github.environments One more federated credential
Switch a service connection to federated credentials azdo.useFederatedCredentials The service connection uses workload identity federation. No secret is generated. Read the plan for what changes.
Resize an IPAM-allocated network numberOfIpAddresses Treat it like a change of address range: read the plan and stop on any replace.
Change tags (team-owned) tags subscription and resource tags updated
Move the subscription to another management group managementGroupId management group association
Rename the subscription azureSubscriptionName subscription rename
Enable or disable hub internet routing network[].InternetSecurityEnabled hub connection updated
Add a region targetRegions.additional + a network[] entry with that region per-region resource group, VNet, LAW, KV, storage

Changing the owner (RBAC owner)

The spoke's Entra ID groups are created with owners taken from adInfo.ad_OwnersMembers (e-mail addresses) and adInfo.ad_OwnersMembersUPN. In modules/ad_groups/main.tf, owners and members are under lifecycle { ignore_changes = [owners, members] }. Editing these lists after the first deployment has no effect.

Change ownership instead by:

  • changing who is in the team groups listed in ProductTeamGroupNames (Entra ID), or
  • adding a different team group to ProductTeamGroupNames and removing the old one, then running the pipeline, or
  • changing the SG_SPOKE_<wl>_<env>_* group owners directly in Entra ID. Terraform ignores these, so the change is not reverted, but it is not recorded in Git either. Record it in the change ticket.

Changing service principal information

The service principal <SPNNamePrefix><wl>-<env> is managed by the spoke canvas:

  • Rotate the secret: the secret is stored in the spoke Key Vault unless federated credentials are configured. It is regenerated by a time_rotating resource (modules/ad_service_principal/main.tf) with rotation_days = SpokeCommon.tenantinfo.SPNSecretrotationPeriod. The new secret is created on the first spoke run after the period has passed, so run the spoke pipeline regularly, or the secret expires.
  • Switch the Azure DevOps service connection to workload identity federation: set azdo.useFederatedCredentials to true.
  • Graph permissions: adInfo.SPNGraphPermissions is read by the Terraform. The schema does not define it, but allows it because adInfo accepts extra keys. Review the plan carefully.

Steps

  1. Edit the spoke JSON in a branch (see Making a change safely). A standard branch name helps, for example feature/SpokeUpdate-<request id>-<workload short name>-<environment>. Some changes are not possible because of limits in Terraform or Azure. For example, you cannot change a subnet that virtual machines use.
  2. Run spoke with spokeGlob set to that one file. Preferably use mode ApproveModifications, so you can read the plan before it is applied. The reference entry files hard-code mode: Apply; see Expose mode and whatIf at run time.
  3. Read the plan. Expect only the changes from the table above. Stop on any destroy / must be replaced that you did not intend. That includes a destroy of azurerm_management_group_subscription_association (a known issue, see Known issues).
  4. Approve or apply.

Verify

Check the changed item in the Azure portal or Entra ID, and ask the requesting team to confirm.

Roll back

Revert the JSON change and run spoke for the file again.