CloudNation - Inspiration

Cloud Adoption Framework: A dive into Terraform implementation

Written by Daan Toes | Nov 6, 2023 10:25:52 AM

In my previous blog I explained what the Cloud Adoption Framework is and why organizations should be using this framework. I showed a conceptual Azure landing zone architecture and explained how its implementation works. In this blog I show how you can roll this out with Terraform code. 

CAF-enterprise-scale-module

To roll out the framework we use a terraform module. This is the terraform-azurerm-caf-enterprise-scale module that is maintained by people from Microsoft, among others. For more information, see the GitHub page Azure/terraform-azurerm-caf-enterprise-scale: Azure landing zones Terraform module (github.com)

Basically, the module ensures the hierarchy of the management groups and a basic set of Policies and Access Control is placed on these management groups. The basic configuration for this is:

/main.tf

 

module "enterprise_scale" {
source  = "Azure/caf-enterprise-scale/azurerm" 
version = "4.2.0" 
default_location = var.location 
providers = { 
azurerm              = azurerm 
azurerm.connectivity = azurerm 
azurerm.management   = azurerm 
} 
root_parent_id = data.azurerm_client_config.core.tenant_id 
root_id        = "myorg" 
root_name      = "My Organization" 

} 

 

 

With this we have rolled out the management groups and their hierarchy. The recommended Policies and Access Controls have been placed on these groups.

Tip: This basic configuration seems small, but if you roll it out, more than 200 resources will be rolled out in Azure. These are often policies and their permissions that are placed on the various management groups. These resources do not cost any money.

We now have a good foundation, but the Landing Zones management group is empty and we want to use our own naming. To change the naming, we need to change the values of root_id and root_name.

In the Landing Zones management group, we want to create two management groups called Workload1 and Workload2. We also put the IDs of the subscriptions that we want in there, the "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" must be replaced with our own specific subscription IDs.

This looks like this:

/main.tf 

module "enterprise_scale" { 

source  = "Azure/caf-enterprise-scale/azurerm" 

version = "4.2.0" 

 

default_location = var.location 

 

providers = { 

    azurerm              = azurerm 

    azurerm.connectivity = azurerm 

    azurerm.management   = azurerm 

  } 

 

root_parent_id = data.azurerm_client_config.core.tenant_id 

root_id        = "es" 

root_name      = "Enterprise-Scale" 

library_path   = "${path.root}/lib" 

 

custom_landing_zones = { 

    "${var.root_id}-Workload1" = { 

      display_name               = "Workload1" 

      parent_management_group_id = "${var.root_id}-landing-zones" 

      subscription_ids           = ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"] 

      archetype_config = { 

        archetype_id   = "online" # this archetype_id refers to the archetype_definition_online.json file in the lib folder 

        parameters     = {} 

        access_control = {} 

      } 

    } 

    "${var.root_id}-Workload2" = { 

      display_name               = "Workload2" 

      parent_management_group_id = "${var.root_id}-landing-zones" 

      subscription_ids           = ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"] 

      archetype_config = { 

        archetype_id   = "online" # this archetype_id refers to the archetype_definition_online.json file in the lib folder 

        parameters     = {} 

        access_control = {} 

      } 

    } 

  } 

} 

Because we want to roll out custom management groups under the Landing Zone management group, we need to create a library folder. The library_path variable points to this folder. In this case our folder is called “lib”.

In the lib folder we create an archetype_definition_online.json. This will be our archetype definition and will be given the archetype_id with the name “online”. 

This definition looks like this:

/lib/archetype_definition_online.json 

{ 

    "online": {  
       "policy_assignments": [ 
           
"Deny-Resource-Locations", 
           
"Deny-RSG-Locations" 

        ], 

        "policy_definitions": [], 

        "policy_set_definitions": [], 

        "role_definitions": [], 

        "archetype_config": { 

            "parameters": { 

                "Deny-Resource-Locations": { 

                    "listOfAllowedLocations": [ 

                        "westeurope", 

                        "northeurope" 

                    ] 

                }, 

                "Deny-RSG-Locations": { 

                    "listOfAllowedLocations": [ 

                        "westeurope", 

                        "northeurope" 

                    ] 

                } 

            }, 

            "access_control": {} 

        } 

    } 

} 

In the archetype definition (the json file above) we give it the name “online” and set two policies. We can use the built-in policies that are in the caf module. In this example we use the built-in policies “Deny-Resource-Locations” and “Deny-RSG-Locations. We define the parameters per policy so that resources may only be rolled out in western and northern Europe.

Tip: See terraform-azurerm-caf-enterprise-scale/modules/archetypes/lib/policy_assignments at main · Azure/terraform-azurerm-caf-enterprise-scale (github.com) for all built-in policies deployed with this module become.

After successfully deploying the code, the management groups structure in Azure looks like this:

 

If we now want to deploy a resource group in the management group “Workload1”, it must comply with the policies. For example, if we want to deploy a resource group in “East US”, we will receive a message that this is not allowed by the policy:

Anyone who works in this Azure environment must comply with this policy, so they do not have the option to deploy cloud resources in another region. In this way, we can ensure that we remain in control of our Azure environment through policies.

There are dozens of policies that can be used to apply policy to the Azure environment. See List of built-in policy definitions - Azure Policy | Microsoft Learn for the built-in policies you can use. It is also possible to create your own policies.

Conclusion

With this basic configuration of the CAF module we can manage and secure our Azure environment using policies and management groups. We have established the hierarchy of the management groups and can define different policies per management group. If all management groups must comply with the same policy(s), this can be assigned to the highest management group, the management groups below it inherit this policy.

The module is very scalable and customizable, making it applicable to any organization. For both small and large enterprise organizations. For more information or questions, you can get in touch with us.