-
Notifications
You must be signed in to change notification settings - Fork 575
[User Guide] Archetype Definitions
Archetypes are used in the Azure landing zone conceptual architecture to describe the Landing Zone configuration using a template-driven approach. The archetype is what fundamentally transforms Management Groups and Subscriptions into Landing Zones.
An archetype defines which Azure Policy and Access control (IAM) settings are needed to secure and configure the Landing Zones with everything needed for safe handover to the Landing Zone owner. This covers critical platform controls and configuration items, such as:
- Consistent role-based access control (RBAC) settings
- Guardrails for security settings
- Guardrails for common workload configurations (e.g. SAP, AKS, WVD, etc.)
- Automate provisioning of critical platform resources such as monitoring and networking solutions in each Landing Zone
This approach provides improved autonomy for application teams, whilst ensuring security policies and standards are enforced.
The archetype_definition
is a template file written in JSON or YAML, used to describe a landing zone archetype. The default archetype definitions can be found in the built-in module library, but custom archetype definitions can also be added to a custom library in the root module.
The archetype definition is associated to the scope (i.e. Management Group) by specifying the archetype_id
within the Landing Zone configuration object.
Both the built-in and custom libraries are also used to store ARM based templates for the Policy Assignments, Policy Definitions, Policy Set Definitions (Initiatives) and Role Definitions.
Role Assignments are an exception as these are defined as part of the archetype_config
instead.
To use a custom library, simply create a folder in your root module (e.g. /lib
) and tell the module about it using the library_path
variable (e.g. library_path = "${path.root}/lib"
).
Save your custom templates in the custom library location and as long as they are valid templates for the resource type and match the following naming conventions, the module will automatically import and use them:
Resource Type | File Name Pattern |
---|---|
Archetype Definitions | **/archetype_definition_*.{json,yml,yaml,json.tftpl,yml.tftpl,yaml.tftpl} |
Policy Assignments | **/policy_assignment_*.{json,yml,yaml,json.tftpl,yml.tftpl,yaml.tftpl} |
Policy Definitions | **/policy_definition_*.{json,yml,yaml,json.tftpl,yml.tftpl,yaml.tftpl} |
Policy Set Definitions | **/policy_set_definition_*.{json,yml,yaml,json.tftpl,yml.tftpl,yaml.tftpl} |
Role Definitions | **/role_definition_*.{json,yml,yaml,json.tftpl,yml.tftpl,yaml.tftpl} |
The decision to store Policy Assignments, Policy Definitions, Policy Set Definitions (Initiatives) and Role Definitions as native ARM was based on a number of factors:
- Policies in Terraform require you to understand how to write significant sections of the resource configuration in the native ARM format, and then convert this to a JSON string within Terraform resource.
- Using a native ARM format makes copying these template assets between ARM and Terraform much easier.
- Terraform doesn't support importing data objects from native Terraform file formats (
.hcl
,.tf
or.tfvar
) so we had to use an alternative to be able to support the custom library model for extensibility and customization.PRO TIP: The module also supports YAML for these files as long as they match the ARM schema.
This template driven approach is designed to simplify the process of defining an archetype and forms the foundations for how the module is able to provide feature-rich defaults, whilst also allowing a great degree of extensibility and customization through the input variables instead of having to fork and modify the module. To increase flexibility when writing these files, we have provided full support for the Terraform templatefile() function, allowing you to create re-usable templates which can be automatically populated with pre-defined template variables from the module, or user-provided template variables. For more information about which values are pre-defined by the module or how to add your own, please refer for the Wiki page for template_file_variables.
The archetype_definition
template contains lists of the Policy Assignments, Policy Definitions, Policy Set Definitions (Initiatives) and Role Definitions you want to create when assigning the archetype to a Management Group. It also includes the ability to set default values for parameters associated with Policy Assignments, and set default Role Assignments.
To keep the archetype_definition
template as lean as possible, we simply declare the value of the name
field from the resource templates (by type). The exception is Role Definitions which must have a GUID for the name
field, so we use the roleName
value from properties
instead.
As long as you follow these patterns, you can create your own archetype definitions to start advanced customization of your Azure landing zone.
This template-based approach was chosen to make the desired-state easier to understand, simplify the process of managing configuration and versioning, reduce code duplication (DRY), and to improve consistency in complex environments.
We have documented some examples showing how to set parameter values for Policy Assignments.
{
"archetype_id": {
"policy_assignments": [
// List of Policy Assignments, as per the "name" field in the library templates
"Policy-Assignment-Name-1",
"Policy-Assignment-Name-2",
"Policy-Assignment-Name-3"
],
"policy_definitions": [
// List of Policy Definitions, as per the "name" field in the library templates
// We recommend only creating Policy Definitions at the root_id scope
"Policy-Definition-Name-1",
"Policy-Definition-Name-2",
"Policy-Definition-Name-3",
"Policy-Definition-Name-4",
"Policy-Definition-Name-5",
"Policy-Definition-Name-6"
],
"policy_set_definitions": [
// List of Policy Set Definitions, as per the "name" field in the library templates
// We recommend only creating Policy Set Definitions at the root_id scope
"Policy-Set-Definition-Name-1",
"Policy-Set-Definition-Name-2"
],
"role_definitions": [
// List of Role Definitions, as per the "properties.roleName" field in the library templates
// We recommend only creating Role Definitions at the root_id scope
"Role-Definition-Name-1"
],
"archetype_config": {
"parameters": {
// Map of parameters, grouped by Policy Assignment
// Key should match the "name" field from Policy Assignment
// Value should be a map containing key-value pairs for each parameter
"Policy-Assignment-Name-1": {
"parameterName1": "myStringValue",
"parameterName2": 100,
"parameterName3": true,
"parameterName4": [
"myListValue1",
"myListValue2",
"myListValue3"
],
"parameterName5": {
"myObjectKey1": "myObjectValue1",
"myObjectKey2": "myObjectValue2",
"myObjectKey3": "myObjectValue3"
}
}
},
"access_control": {
// Map of Role Assignments to create, grouped by Role Definition name
// Key should match the "name" of the Role Definition to assign
// Value should be a list of strings, specifying the Object Id(s) (from Microsoft Entra ID) of all identities to assign to the role
"Reader": [
"00000000-0000-0000-0000-000000000000",
"11111111-1111-1111-1111-111111111111",
"22222222-2222-2222-2222-222222222222"
],
"Role-Definition-Name-1": [
"33333333-3333-3333-3333-333333333333"
]
}
}
}
}
WARNING The
jsondecode()
function used by Terraform doesn't support comments in JSON. Please also note that HCL objects are Case-Sensitive so the JSON object must be created with the correct character case on anything referenced by Terraform. Typically this applies to eachkey
in an object but there are also situations where thevalue
also needs to be interpreted by the module. For archetype definitions, the case of all values within each section must match those used in the mapped field for each template being assigned. Incorrect casing can result interraform plan
identifying unnecessary resource updates. For example, the Azure REST API returns"type": "String"
in parameter blocks, regardless of what case was used to create the resource. Not using the same casing in your source templates can result in Terraform trying to update resources when no real changes have occurred.
Specifying an archetype_id
value is mandatory for all Management Groups created by the module.
The default library includes a default_empty
archetype definition which is useful when defining Management Groups which only require Role Assignments, or are being used for logical segregation of Landing Zones under a parent archetype.
You can assign this to any Landing Zone definition, using the archetype_config
> archetype_id
value as per the following custom_landing_zones
example:
custom_landing_zones = {
example-landing-zone-id = {
display_name = "Example Landing Zone"
parent_management_group_id = "tf-landing-zones"
subscription_ids = []
archetype_config = {
archetype_id = "default_empty"
parameters = {}
access_control = {}
}
}
}
This is equivalent to creating a standard Management Group without creating any custom Policy Assignments, Policy Definitions, Policy Set Definitions (Initiatives) or Role Definitions.
Role Assignments can be created using the custom_landing_zones.${management_group_id}.archetype_config.access_control
object scope.
NOTE: that you still need to provide a full and valid Landing Zone object as per the example above.
The archetype_config
object appears in a number of places and can be used to control the configuration settings of your deployment.
Below is the required structure for the archetype_config
object:
myconfig = object({
archetype_id = string
parameters = map(any)
access_control = map(list(string))
})
The archetype_config
object must contain the following properties:
-
archetype_id
specifies whicharchetype_definition
to associate with the current scope. This must reference a validarchetype_definition
from the built-in or custom library. -
parameters
provides the option to set parameter values for any Policy Assignment(s) specified within the chosen archetype definition. To target a specific Policy Assignment, create a newmap()
entry using the Policy Assignmentname
field as thekey
. Thevalue
should be anobject({})
containingkey/value
pairs for eachparameter
needed by the Policy Assignment. To simplify working with parameters at different scopes within the module, parameters for a given policy assignment are merged in the following order:- Default values from within the base definition or initiative
- Values defined within a policy assignment template
- Values provided within the
archetype_config.parameters
object from an archetype definition template - Values managed by the module (such as the
logAnayltics
value commonly set in many of our bundled policy assignments) - Values provided within the
archetype_config.parameters
object from either thearchetype_config_overrides
orcustom_landing_zones
input
NOTE: Parameters are specified as simple
key/value
pairs in the module, and do not require the same structure used in native ARM templates. -
access_control
provides the option to add user-specified Role Assignments which will be added to the specified Management Group. To avoid a direct dependency on the Microsoft Entra ID Provider, this module requires the input to be a list of Object IDs for each Microsoft Entra object you want to assign the specified permission. To add your own Role Assignments, specify thename
of the Role Definition you want to assign as thekey
, and provide a list of Microsoft Entra Object IDs to assign to this role as thevalue
.
You will find the archetype_config
object in the following places:
- Within each
archetype_definition
template (as per the example above) - Within each entry of the
custom_landing_zones
input variable - As the value of each (optional) entry in the
archetype_config_overrides
input variable
When planning your configuration, keep in mind that the module uses a hierarchy to determine which values to apply.
-
For
parameters
entries are merged at the Policy Assignment level, so all requiredparameters
must be specified per Policy Assignment. This allows you to override parameter values for as many or as few Policy Assignments as needed, but you cannot selectively override individual parameter values whilst inheriting others from a lower scope. -
For
access_control
entries are merged at the Role Definition level, so any Role Assignments found under a duplicate Role Definition name will be overwritten by the higher scope.
This wiki is being actively developed
If you discover any documentation bugs or would like to request new content, please raise them as an issue or feel free to contribute to the wiki via a pull request. The wiki docs are located in the repository in the docs/wiki/
folder.
- Home
- User guide
- Video guides
-
Examples
- Level 100
- Level 200
-
Level 300
- Deploy multi region networking with custom settings (Hub and Spoke)
- Deploy multi region networking with custom settings (Virtual WAN)
- Deploy with Zero Trust network principles (Hub and Spoke)
- Deploy identity resources with custom settings
- Deploy management resources with custom settings
- Expand built-in archetype definitions
- Create custom policies, initiatives and assignments
- Override module role assignments
- Control policy enforcement mode
- Policy assignments with user assigned managed identities
- Level 400
- Frequently Asked Questions
- Troubleshooting
- Contributing