Azure Citadel
  • Blogs

  • Azure Arc
    • Overview
    • Azure Arc-enabled Kubernetes
      • Prereqs
      • Background
      • Deploy Cluster
      • Connect to Arc
      • Enable GitOps
      • Deploy Application
      • Enable Azure AD
      • Enforce Policy
      • Enable Monitoring
      • Enable Azure Defender
      • Enable Data Services
      • Enable Application Delivery
    • Azure Arc-enabled Servers
      • Prereqs
      • Scenario
      • Hack Overview
      • Azure Landing Zone
      • Arc Pilot resource group
      • Azure Monitoring Agent
      • Additional policy assignments
      • Access your on prem VMs
      • Create onboarding scripts
      • Onboarding using scripts
      • Inventory
      • Monitoring
      • SSH
      • Windows Admin Center
      • Governance
      • Custom Script Extension
      • Key Vault Extension
      • Managed Identity
    • Useful Links
  • Azure CLI
    • Install
    • Get started
    • JMESPATH queries
    • Integrate with Bash
  • Azure Landing Zones
    • ALZ Accelerator
      • Prereqs
      • Elevate
      • Bootstrap
      • Demote
      • Components
    • Deploy an Azure Landing Zone
      • Create an initial ALZ config
      • Add a local override library
      • Test locally
      • Run through the CI/CD workflow
    • Libraries
      • What is a library?
      • Policies, Assignments and Roles
      • Archetypes, Overrides and Architecture
      • Metadata and Policy Default Values
      • Custom libraries
    • Example Library Configs
      • Azure Landing Zone library
      • Azure Landing Zone library with overrides
  • Azure Lighthouse
    • Minimal Lighthouse definition
    • Using service principals
    • Privileged Identity Management
  • Azure Policy
    • Azure Policy Basics
      • Policy Basics in the Azure Portal
      • Creating Policy via the CLI
      • Deploy If Not Exists
      • Management Groups and Initiatives
    • Creating Custom Policies
      • Customer scenario
      • Policy Aliases
      • Determine the logic
      • Create the custom policy
      • Define, assign and test
  • Marketplace
    • Introduction
      • Terminology
      • Offer Types
    • Partner Center
    • Offer Type
    • Publish a VM Offer HOL
      • Getting Started
      • Create VM Image
      • Test VM Image
      • VM Offer with SIG
      • VM Offer with SAS
      • Publish Offer
      • Other VM Resources
    • Publish a Solution Template HOL
      • Getting Started
      • Create ARM Template
      • Validate ARM Template
      • Create UI Definition
      • Package Assets
      • Publish Offer
    • Publish a Managed App HOL
      • Getting Started
      • Create ARM Template
      • Validate ARM Template
      • Create UI Definition
      • Package Assets
      • Publish Offer
    • Managed Apps with AKS HOL
    • Other Managed App Resources
    • SaaS Offer HOLs
    • SaaS Offer Video Series
      • Video 1 - SaaS Offer Overview
      • Video 2 - Purchasing a SaaS Offer
      • Video 3 - Purchasing a Private SaaS Plan
      • Video 4 - Publishing a SaaS Offer
      • Video 5 - Publishing a Private SaaS Plan
      • Video 6 - SaaS Offer Technical Overview
      • Video 7 - Azure AD Application Registrations
      • Video 8 - Using the SaaS Offer REST Fulfillment API
      • Video 9 - The SaaS Client Library for .NET
      • Video 10 - Building a Simple SaaS Landing Page in .NET
      • Video 11 - Building a Simple SaaS Publisher Portal in .NET
      • Video 12 - SaaS Webhook Overview
      • Video 13 - Implementing a Simple SaaS Webhook in .NET
      • Video 14 - Securing a Simple SaaS Webhook in .NET
      • Video 15 - SaaS Metered Billing Overview
      • Video 16 - The SaaS Metered Billing API with REST
  • Microsoft Fabric
    • Theory
    • Prereqs
    • Fabric Capacity
    • Set up a Remote State
    • Create a repo from a GitHub template
    • Configure an app reg for development
    • Initial Terraform workflow
    • Expanding your config
    • Configure a workload identity
    • GitHub Actions for Microsoft Fabric
    • GitLab pipeline for Microsoft Fabric
  • Packer & Ansible
    • Packer
    • Ansible
    • Dynamic Inventories
    • Playbooks & Roles
    • Custom Roles
    • Shared Image Gallery
  • Partner Admin Link
    • Understanding PAL
    • Service principals with credentials
    • PAL tagging with a service principal
    • CI/CD pipelines & OpenID Connect
    • User and guest IDs
    • Azure Lighthouse & PAL
    • PAL FAQ
  • REST API
    • REST API theory
    • Using az rest
  • Setup
  • Sovereign Landing Zones
    • ALZ Accelerator
      • Prereqs
      • Elevate
      • Bootstrap
      • Demote
      • Components
    • Deploy Sovereign Landing Zone
      • Create an initial SLZ config
      • Add a local override library
      • Test locally
      • Run through the CI/CD workflow
    • Libraries
      • What is a library?
      • Policies, Assignments and Roles
      • Archetypes, Overrides and Architecture
      • Metadata and Policy Default Values
      • Custom libraries
    • Reference Library Configs
      • Sovereign Landing Zone
      • Sovereign Landing Zone library with overrides
      • SLZ extended with a country pack
  • Terraform
    • Fundamentals
      • Initialise
      • Format
      • Validate
      • Plan
      • Apply
      • Adding resources
      • Locals and outputs
      • Managing state
      • Importing resources
      • Destroy
    • Get set up for Terraform
      • Cloud Shell
      • macOS
      • Windows with PowerShell
      • Windows with Ubuntu in WSL2
    • Using AzAPI
      • Using the REST API
      • azapi_resource
      • Removing azapi_resource
      • azapi_update_resource
      • Data sources and outputs
      • Removing azapi_update_resource
  • Virtual Machines
    • Azure Bastion with native tools & AAD
    • Managed Identities

  • About
  • Archive
  1. Home
  2. Azure Landing Zones
  3. Libraries
  4. Custom libraries
Custom libraries
Custom libraries
Libraries
What is a library?
Policies, Assignments and Roles
Archetypes, Overrides and Architecture
Metadata and Policy Default Values
Custom libraries

Custom libraries

Creating custom libraries to be hosted in GitHub, checking the contents, generating documentation, and creating tags and releases for sematic versioning.

Table of Contents

Overview

The focus of the deploy lab series for both Azure Landing Zone and Sovereign Landing Zone was the platform libraries themselves, and the local override library that you then added to your repo before testing and deploying via the CI/CD pipelines.

For most customers this will be all they ever need.

The platform libraries will be updated over time, and you have control on how and when you update to a more recent version using the semantic versioning specified in the ref argument for either the alz provider block’s library_references array or in the local override metadata’ dependencies array.

The local override library can be use to add or remove whole definitions or assignments, and the module block can be used to modify those assignments. The local library could also be used to host custom definitions and assignments and extend at that level.

Environment variable are already embedded into the GitHub config that the ALZ Accelerator created, and it wouldn’t take too much to extend that with a more complex pipeline structure for a canary approach.

So, what is the point of a custom library hosted in GitHub?

There are a main reasons, and I’ll give a single word for each: reuse and security.

The main reason is reuse and it particularly valid for the work I do with Microsoft partners. Here they can pull together their own custom definitions into a custom repo and reuse for multiple Azure Landing Zone customers, including support for multiple archetypes and architectures for common patterns, avoiding local overriding by default.

The value is even greater in sovereignty scenarios, where the baseline Sovereign Landing Zone library can be extended and customised with packs specific to requirement for specific regions, countries, and industry compliancy demands.

A benefit is that the custom libraries support semantic versioning, which allows release control at a customer level.

Finally, there is the question of security which is enhanced by keeping the configs cleanly outside of the main customer repo. This allows for a more flexible security model where the right group has access to make feature branch changes to the customer repo, whilst the separate repos for custom library user and for CI/CD workflows remain outside and can have separate RBAC permissions.

These pages specify GitHub for hosting the custom library, but it could be any valid URL format that go-getter can access.

It is assumed that you will be proficient with creating custom policies, assignments and role definitions, and comfortable with git and GitHub. Therefore this page will be reference level to give a few key pointers that you may find useful.

Reference repos

This series has described the assets and structure of a library, but it is always useful to look at examples as a reference point when creating your own custom libraries.

Platform libraries found in the platform subfolder of https://aka.ms/alz/library:

  • platform/alz,

    The main Azure Landing Zone repo has a huge selection of assets to use as a reference.

  • platform/slz

    The Sovereign Landing Zone library is a good example of a “stacked” library, extending the dependency (alz) and creating new management groups in the architecture. This is the repo I use most often as a reference when creating custom libraries.

  • platform/amba

    The Azure Monitor Baseline Alerts library is more standalone and assumes that the management group hierarchy is already in place. Note the "exists": true against the management groups in the architecture files.

    This library is useful as it serves a slightly different purpose with its Deploy If Not Exists policies when compared to the governance focused alz and slz libraries. The library could also be “sideloaded” as the second library in an array if you wanted both alz/slz and amba deployed together.

Additional example library repos found pinned in my https://github.com/richeney-org GitHub organisation:

  • Azure-Citadel-Custom-Library

    Example single custom library for Azure Landing Zones’ alz provider for partners or organisations that repeatably deploy customised landing zones.

  • Sovereign-Landing-Zone-Packs

    Example repo capable of hosting multiple libraries to extend a Sovereign Landing Zone to meet country and industry requirements. Each library will be in a subfolder.

Construct your repo to match the format of one of these.

Checking assets

The library specific constructs - archetypes, overrides, architectures, metadata, policy default values - are all pretty simple, so the key is to check that your assets - policies, policy sets, assignments, and role definitions - are all functioning correctly.

All of the assets are designed for creation and use at a management group level. You may wish to create one specifically for testing, e.g.:

az account management-group create --name "test" --display-name "Library test scope"

This will allow you to test creation without affecting any subscriptions or their resources.

These are the example commands that I use to check that my JSON files are syntactically sound and create the Azure resources correctly.

Whether your policy and role definitions actually achieve the intended functionality is outside the scope of these pages, and you naturally use these commands at your own risk.

  1. Define the scope

    The example is for a management group called “test”. Change if required.

    scope="/providers/Microsoft.Management/managementGroups/test"
    
  2. Set the file variable

    It is assumed that you have already ensured that the name value within the file matches the prefix for the filename.

    Example policy definition filename. Change as required.

    file="policy_definitions/Enforce-KV-Premium.alz_policy_definition.json"
    

    Example policy set definition filename. Change as required.

    file="policy_set_definitions/Deny-NL-Global.alz_policy_set_definition.json"
    

    Example policy assignment filename. Change as required.

    file="policy_assignments/Deny-NL-Global.alz_policy_assignment.json"
    

    Example role definition filename. Change as required.

    file="role_definitions/fabric_reader.alz_role_definition.json"
    
  3. Test using the REST API

    The REST API is preferable to the matching CLI and PowerShell cmdlets as they cannot use the full JSON file definitions.

    name="$(basename $file .alz_policy_definition.json)"
    uri="${scope}/providers/Microsoft.Authorization/policyDefinitions/${name}?api-version=2021-06-01"
    az rest --method put --url "$uri" --body @"$file"
    
    name="$(basename $file .alz_policy_set_definition.json)"
    uri="${scope}/providers/Microsoft.Authorization/policySetDefinitions/${name}?api-version=2021-06-01"
    az rest --method put --url "$uri" --body @"$file"
    
    name="$(basename $file .alz_policy_assignment.json)"
    uri="${scope}/providers/Microsoft.Authorization/policyAssignments/${name}?api-version=2023-04-01"
    az rest --method put --url "$uri" --body @"$file"
    
    name="$(basename $file .alz_role_definitioncopilot.json)"
    uri="${scope}/providers/Microsoft.Authorization/roleDefinitions/${name}?api-version=2022-04-01"
    az rest --method put --url "$uri" --body @"$file"
    
  4. Delete

    Assuming that the definitions were successfully created, you may want to tidy up and remove them. Here are the commands to match the example names. Update as required.

    az policy definition delete --management-group test --name "Enforce-KV-Premium"
    
    az policy set-definition delete --management-group test --name  "Deny-NL-Global"
    
    az policy assignment delete --scope /providers/Microsoft.Management/managementGroups/test --name "Deny-NL-Global"
    
    az role definition delete --scope /providers/Microsoft.Management/managementGroups/test --name  "fabric_reader"
    

Using the alzlibtool

The alzlibtool is a standalone CLI tool that is part of the github.com/Azure/alzlib source repo. The tool has many uses, but I primarily use it to

  • check and validate a custom library
  • generate the documentation in the style seen for the platform libraries’ README.md files

You will need to have Go installed.

Install

go install github.com/Azure/alzlib@latest

By default this will install azlibtool into your $HOME/go/bin directory.

Testing libraries

The alzlibtool can validate your custom library structure and content to ensure it conforms to the expected format.

alzlibtool check library .

This assumes you are running in the root of your library.

Creating documentation

The alzlibtool can automatically generate comprehensive documentation for your custom library in markdown format, including the mermaid diagrams for the architecture hierarchy if it contains a hierarchy file. The command only works if your library can pass the check.

Note that this will command will overwrite the current directories README.md file if it exists. You may want to remove the redirection, or pick another filename.

Generate documentation and output to README.md.

alzlibtool document library . > README.md

This creates markdown files documenting all archetypes, policies, assignments and other library components. You can then customise.

Note that the provide block generated for the Usage section is in the format for a platform library, with path and ref arguments. Update to your custom_url format, e.g.:

provider "alz" {
  library_references = [
    {
      custom_url = "github.com/richeney-org/Sovereign-Landing-Zone-Packs//country/nl/bio?ref=2026.01.0"
    }
  ]
}

Semantic versioning, tags and releases

Follow the formatting of the platform libraries by adding your own tags and releases.

This GitHub CLI command to create releases is great. Once you have committed and pushed your repo, you can use this to interactively and it will configure a tag on the local and origin, and it will create a release in GitHub.

gh release create 2026.01.0

Modify the semantic version to match the right yyyy.mm.v for your release. This will also be interactively suggested for the Title, so hit enter to accept.

If you select Write using generated notes as template then it will generate default release notes based on your commits and their descriptions and open in your default editor. Save.

You can then publish, save as draft or cancel.

Note that it is the tag which is specified in your ref value, not the GitHub releases per se. However, the standard for these libraries is to ensure that the same value is used for both to avoid unnecessary confusion.

Source: https://www.azurecitadel.com/alz/library/custom/
Published: 07 Jan 2026
Printed:
Metadata and Policy Default Values Custom libraries Next