Unable to configure maintenance configuration for Patching

When trying to create ‘azurerm_maintenance_configuration’, additional properties are required to set patch classifications.

in ARM we use the following

"properties": {
    "maintenanceScope": "InGuestPatch",
    "installPatches": {
        "linuxParameters": {
            "classificationsToInclude": [
                "Critical",
                "Security"
            ],
            "packageNameMasksToExclude": null,
            "packageNameMasksToInclude": null
        },
        "windowsParameters": {
            "classificationsToInclude": [
                "Critical",
                "Security"
            ],
            "kbNumbersToExclude": null,
            "kbNumbersToInclude": null
        },
        "rebootSetting": "NeverReboot"
    },
    "extensionProperties": {
        "InGuestPatchMode": "User"
    },
    "maintenanceWindow": {
        "timeZone": "UTC",
        "startDateTime": "2022-10-07 01:00",
        "expirationDateTime": null,
        "duration": "01:10",
        "recurEvery": "2Hour"
    }
}

meanwhile in Terraform there is no option to set these.

resource "azurerm_maintenance_configuration" "example" {
  name                = "example-mc"
  resource_group_name = ...
  location            = ...
  scope               = "InGuestPatch"
  visibility          = "Custom"
  
  window {
    time_zone            = "UTC"
    start_date_time      = formatdate("YYYY-MM-DD 01:00", timestamp())
    expiration_date_time = null
    duration             = "01:10"
    recur_every          = "2Hour"
  }
  
  properties = {
     //Unable to set complex objects as properties is contrained to type pluginsdk.TypeMap that does not allow for key:values, a JSON string might be a work around for this?
     //extension_properties.in_guest_patch_mode =  "Platform" <-- not valid
     ????
  }
 }

Would appreciate some input as to how could this be accomplished without having to inject ARM template into our terraform.

I have an indirect approach, you can try…

resource “azurerm_template_deployment” “update_config_standard_windows-prod” {
name = “update-config-standard-windows-prod”
resource_group_name = azurerm_resource_group.example.name
deployment_mode = “Incremental”
template_body = jsonencode(
{
“$schema” = “http://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#
contentVersion = “1.0.0.0”

            resources      = [
                {
                    apiVersion = "2021-09-01-preview"
                    location   = "WestEurope"
                    name       = "mytestingmaintainanceconfig"
                    properties = {
                        extensionProperties = {
                            InGuestPatchMode = "User"
                        }
                        installPatches      = {
                            linuxParameters   = {
                                classificationsToInclude  = [
                                    "Critical",
                                    "Security",
                                ]
                                packageNameMasksToExclude = null
                                packageNameMasksToInclude = null
                            }
                            rebootSetting     = "RebootIfRequired"
                            windowsParameters = {
                                classificationsToInclude = [
                                    "Critical",
                                    "Security",
                                ]
                                kbNumbersToExclude       = null
                                kbNumbersToInclude       = null
                            }
                        }
                        maintenanceScope    = "InGuestPatch"
                        maintenanceWindow   = {
                            duration           = "02:55"
                            expirationDateTime = null
                            recurEvery         = "1Day"
                            startDateTime      = "2022-10-14 00:00"
                            timeZone           = "India Standard Time"
                        }
                    }
                    tags       = {}
                    type       = "Microsoft.Maintenance/maintenanceConfigurations"
                },
            ]
        }
    )
}

Hey,

I’ve just been looking at this and I think it’s because the options to configure updates in maintenance configurations are in a preview API.

I’ve used AzAPI to get round it:

resource "azapi_resource" "updateManagementSchedule" {
  for_each = var.update_method == "modern" ? local.updateSchedule : {}

  type      = "Microsoft.Maintenance/maintenanceConfigurations@2021-09-01-preview"
  name      = "${var.customer_prefix}-maintenanceSchedule-${var.location_short}-${each.key}"
  location  = var.location
  parent_id = azurerm_resource_group.update_mgmt.id

  body = jsonencode(
    {
      properties = {
        maintenanceScope = "InGuestPatch"
        installPatches = {
          linuxParameters = {
            classificationsToInclude = [
              "Critical",
              "Security"
            ]
          }
          windowsParameters = {
            classificationsToInclude = [
              "Critical",
              "Security"
            ]
            kbNumbersToExclude = null
            kbNumbersToInclude = null
          }
          rebootSetting = "RebootIfRequired"
        }
        extensionProperties = {
          InGuestPatchMode = "User"
        }
        maintenanceWindow = {
          startDateTime      = each.value["period"] == "AM" ? "${formatdate("YYYY-MM-DD", timeadd(timestamp(), "24h"))} 00:00" : "${formatdate("YYYY-MM-DD", timeadd(timestamp(), "24h"))} 18:00"
          duration           = "04:00"
          timeZone           = "GMT Standard Time"
          expirationDateTime = null
          recurEvery         = "1Month ${values(each.value["weekOccurance"])[0]} ${each.value["day"]}"
        }
      }
    }
  )
}

Thanks guys,

I initially tried the azurem_template_deployment but had some issues with it specially around assignment, a bit more search and I came accross the AzApi provider ( glad i found it )

and my solutions is fairly identical to @RAWRitsCloud , but for completness I added the configuration assignments bellow too. :grinning:

resource "azapi_resource" "vm_maintenance" {
  type      = "Microsoft.Maintenance/maintenanceConfigurations@2021-09-01-preview"
  name      = "${local.internalName}-vm-${var.stage}-mc"
  parent_id = azurerm_resource_group.rg.id
  location  = azurerm_resource_group.rg.location

  body = jsonencode({
    properties = {
      visibility          = "Custom"
      namespace           = "Microsoft.Maintenance"
      maintenanceScope    = "InGuestPatch"
      extensionProperties = {
        "InGuestPatchMode" = "User"
      }
      maintenanceWindow = {
        startDateTime      = formatdate("YYYY-MM-DD 01:00", timestamp())
        expirationDateTime = null
        duration           = "01:10"
        timeZone           = "UTC"
        recurEvery         = "3Hour"
      }
      installPatches = {
        linuxParameters = {
          classificationsToInclude  = ["Critical", "Security"]
          packageNameMasksToExclude = null
          packageNameMasksToInclude = null
        }
        windowsParameters = {
          classificationsToInclude = ["Critical", "Security"]
          kbNumbersToExclude       = null
          kbNumbersToInclude       = null
        }
        rebootSetting = "RebootIfRequired"
      }
    }
  })

  tags = module.tags.tags
}

resource "azapi_resource" "vm_maintenance_assignment" {
  type      = "Microsoft.Maintenance/configurationAssignments@2021-09-01-preview"
  name      = "vm-${var.targetSiteId}-${var.stage}-mca"
  parent_id = azurerm_windows_virtual_machine.vm.id
  location  = azurerm_windows_virtual_machine.vm.location

  body = jsonencode({
    properties = {
      maintenanceConfigurationId = azapi_resource.vm_maintenance.id
    }
  })
}
1 Like

I had a look through the Go Code of the provider and it is using the previous version sadly of the API!

I’m trying to write a policy to do the configuration assignment based on a tag value! Thanks for the completeness of the code :slight_smile: