Deploy Microsoft Defender for Cloud via Terraform
Published Jul 01 2022 12:46 PM 10K Views

Terraform is an Infrastructure as a Code tool created by Hashicorp. It’s used to manage your infrastructure in Azure, as well as other clouds. In this article, we’ll be showing you how to deploy Microsoft Defender for Cloud (MDC) using Terraform from scratch. This way if you use Terraform, it’s recommended that you stick entirely with Terraform and don’t use any other management methods such as the Azure Portal.


As part of using Terraform to manage MDC, you will need to setup the Terraform configuration in a workspace including the Azure Resource Manager (RM) provider which configures your Azure resources. In this workspace, you’ll have the following files:

  • The declarative configuration of the state of your MDC deployment. This is where all the updates for your Azure resources are performed, including the deployment of MDC.
  • Contains different values per environment e.g., development vs production environment.
  • Declares information that you only determine after deployment

The following commands for Terraform are most crucial for you to know:




Terraform init




  • Summary: Initialize Terraform.
  • Typically run this once or just when adding in new providers or new versions
  • This will parse through all the workspace files to create an initial state of determining what is needed e.g., plugins referenced in the file e.g., azure plugin.
  • Result: Once you run this file It will download these files to a terraform subfolder called .terraform subfolder where it will store the Azure RM provider.




Terraform plan




  • Summary: View the changes that will be applied.
  • Creates an execution plan of the actions needed to make the current state match the desired configuration in the terraform files.
  • No changes in Azure will be made with this command, it will just show you me what will be done but won’t do any of the changes.




Terraform apply




  • Summary: Applies the changes from to your Azure environment.


Setup Terraform environment

  1. Go to Downloads | Terraform by HashiCorp and download the Terraform file relevant to your device.
  2. Then move the downloaded Terraform application in a directory of your choice.
  3. You will need to add the path that Terraform is found in as an environment variable if you’re using Windows. If this still doesn’t work, then use the following command:




$env:PATH =$env:PATH+";'<path to Terraform installation directory>”"





  1. Go to the Microsoft Defender for Cloud GitHub repository and clone the Terraform configuration to the same directory. 
  2. Open the directory that you just cloned in Visual Studio Code or your preferred source code editor.
  3. In the terminal of the editor, test that Terraform has been installed correctly by using the following command:




terraform -version




Now you have confirmed that Terraform has been correctly installed.


Azure RM provider

To manage Azure resources with Terraform, you need to use the Azure RM provider. In a file, you will place the following Terraform declarations, which state you are going to work with a minimum Terraform and Azure RM version:





terraform {
  required_version = ">=0.12"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~>2.0"
provider "azurerm" {
  features {}





This providers declaration will be used next by the Terraform initialization procedure to set itself up for Azure management. See more guidance on this provider in the Terraform resources for MDC section.


Configure Terraform

  1. First thing you need to do is logging in to Azure, using the following command (your web browser will open up a new tab asking you to sign in with your Azure credentials):




az login





     2. You will need to initialize Terraform to prepare the current working directory to be used with Terraform and to install the required providers, using the following command:




terraform init






  1. Run the following command to determine what changes are required in Azure to match the file:




terraform plan




This allows you to see what changes are different from your and what is in your Azure environment.  All the Azure configuration should go in the file.


  1. When you’re satisfied with the proposed changes, then you run the following command to actually apply the changes:




terraform apply





You now have the configuration needed for MDC.

You can make further changes to your file which will be incorporated to your Azure environment when you run the terraform apply command again.


Note: Once you start using Terraform to deploy your Azure resources, it’s a best practise to continue using terraform for this. Try to avoid using the Azure Portal UI to make further changes as that may cause issues in your Terraform configuration.


Terraform resources for MDC

There are many Terraform resources available for setting up MDfC. You can browse for them in the Azure RM Terraform provider documentation. You will notice they appear aggregated under “Security Center”, which was the previous brand for MDfC. In this section, you will learn which Terraform resources to use for each MDfC setup step, for a particular Azure subscription.

Many of the Terraform examples below are going to reference the current Azure subscription ID we are working with. This is done by means of a data declaration which stores the current Azure subscription properties:





data "azurerm_subscription" "current" {}





Note: The example code below should go into your file.


Enabling the default Azure Security Benchmark Policy initiative

After an Azure Subscription is registered for the Microsoft.Security resource provider – this should have at least happened automatically after you ran terraform init –, MDC will eventually enable the default Azure Policy initiative for Azure Security Benchmark, which fuels its Security Posture recommendations. As this will happen only after some hours, you may want to leverage Terraform to enable it yourself and speed things up.





resource "azurerm_subscription_policy_assignment" "asb_assignment" {
  name                 = "azuresecuritybenchmark"
  display_name         = "Azure Security Benchmark"
  policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8"
  subscription_id      =





We are using the Policy Assignment resource applied at the Subscription level and we are referring to the Azure Security Benchmark Policy Initiative ID. You will notice the use of the data.azurerm_subscription.current data resource we declared earlier, to populate the Subscription ID.


Enabling MDC Plans

Now that we’ve already set up Security Posture, let’s move on to Workload Protection. After choosing which Defender Plans you want to enable, you’ll declare a Terraform resource for each plan.




resource "azurerm_security_center_subscription_pricing" "mdc_arm" {
  tier          = "Standard"
  resource_type = "Arm"

resource "azurerm_security_center_subscription_pricing" "mdc_servers" {
  tier          = "Standard"
  resource_type = "VirtualMachines"





In the examples above, we are enabling Defender for ARM and Defender for Servers. For other plans, check out the Terraform documentation.


Enabling integrations with MDE and MDCA

The integrations with Microsoft Defender for Endpoint and Microsoft Defender for Cloud Apps are enabled by default, but you may want to manage them as code.





resource "azurerm_security_center_setting" "setting_mcas" {
  setting_name = "MCAS"
  enabled      = false

resource "azurerm_security_center_setting" "setting_mde" {
  setting_name = "WDATP"
  enabled      = true





Again, there is a specific Terraform resource to enable MDC integrations. We are using the same resource for both integrations, just changing the setting name: MCAS for Microsoft Defender for Cloud Apps and WDATP for Microsoft Defender for Endpoint.


Setting up security contacts

If MDC needs to notify you about a security incident, it’s a good idea to have e-mail and phone contacts set up.





resource "azurerm_security_center_contact" "mdc_contact" {
  email = ""
  phone = "+351919191919"
  alert_notifications = true
  alerts_to_admins    = true





The phone property is the only optional one. The alert_notifications property enables/disables sending notifications to the security contact, while the alerts_to_admins is about sending notifications to the Azure Subscription administrators.


Enabling Log Analytics agent auto-provisioning

OK, now that we have set the basics up, let’s configure more advanced features, such as auto-provisioning Log Analytics agents, in the context of the Defender for Servers plan. This involves multiple steps and Azure resources. First, we must turn auto-provisioning on:





resource "azurerm_security_center_auto_provisioning" "auto-provisioning" {
  auto_provision = "On"





There’s a specific resource for that and it’s very simple to deal with. It’s just an On/Off property. Next, we are going to associate Defender for Servers to a specific Log Analytics workspace.





resource "azurerm_security_center_workspace" "la_workspace" {
  scope        =
  workspace_id = "/subscriptions/<subscription id>/resourcegroups/<resource group name>/providers/microsoft.operationalinsights/workspaces/<workspace name>"





The declaration above will work for an existing Log Analytics workspace. If you want to create the Log Analytics workspace together with MDC, you will use a slightly different approach:




resource "azurerm_resource_group" "security_rg" {
  name     = "security-rg"
  location = "West Europe"

resource "azurerm_log_analytics_workspace" "la_workspace" {
  name                = "mdc-security-workspace"
  location            = azurerm_resource_group.security_rg.location
  resource_group_name =
  sku                 = "PerGB2018"

resource "azurerm_security_center_workspace" "la_workspace" {
  scope        =
  workspace_id =





In the declarations above, we create a Resource Group and Log Analytics Workspace and then reference its ID it in the MDC workspace resource.


Enabling Vulnerability Assessment auto-provisioning

Unlike the Log Analytics counterpart, Vulnerability Assessment auto-provisioning is configured with the help of an Azure Policy assignment. The choice between leveraging Qualys or MDE vulnerability assessment is done as a Policy assignment parameter.




resource "azurerm_subscription_policy_assignment" "va-auto-provisioning" {
  name                 = "mdc-va-autoprovisioning"
  display_name         = "Configure machines to receive a vulnerability assessment provider"
  policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/13ce0167-8ca6-4048-8e6b-f996402e3c1b"
  subscription_id      =
  identity {
    type = "SystemAssigned"
  location = "West Europe"
  parameters = <<PARAMS
{ "vaType": { "value": "mdeTvm" } }

resource "azurerm_role_assignment" "va-auto-provisioning-identity-role" {
  scope              =
  role_definition_id = "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd"
  principal_id       =[0].principal_id





In the example above, we chose the MDE vulnerability assessment (mdeTvm value for the vaType Policy parameter). If you prefer to use Qualys, then you must specify default for the vaType parameter or simply remove the parameters block.

We are also assigning the Security Admin role to the Managed Identity that will be used to perform the automatic provisioning of the Vulnerability Assessment solution.


Configuring Continuous Export settings

The last Terraform resource for MDC we cover in this article is the one allowing you to configure Continuous Export settings. You have many configuration possibilities available. In the example below, we are exporting to a specific Log Analytics workspace High/Medium Security Alerts and all the Secure Score controls. We are referring to a Log Analytics workspace ID that was declared in the same file.




resource "azurerm_security_center_automation" "la-exports" {
  name                = "ExportToWorkspace"
  location            = azurerm_resource_group.security_rg.location
  resource_group_name =

  action {
    type              = "loganalytics"
    resource_id       =

  source {
    event_source = "Alerts"
    rule_set {
      rule {
        property_path  = "Severity"
        operator       = "Equals"
        expected_value = "High"
        property_type  = "String"
      rule {
        property_path  = "Severity"
        operator       = "Equals"
        expected_value = "Medium"
        property_type  = "String"

  source {
    event_source = "SecureScores"

  source {
    event_source = "SecureScoreControls"

  scopes = [ ]





In summary, this article covered how to deploy Microsoft Defender for Cloud using Terraform.

Huge thanks to the reviewers of this post:

@Safeena Begum Lepakshi, Senior Program Manager, Microsoft Defender for Cloud

@Yuri Diogenes , Principal PM Manager, Microsoft Defender for Cloud


Version history
Last update:
‎Aug 04 2022 11:01 AM
Updated by: