diff --git a/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source.go b/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source.go new file mode 100644 index 000000000000..58c1a361810d --- /dev/null +++ b/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source.go @@ -0,0 +1,143 @@ +package policy + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/guestconfiguration/mgmt/2020-06-25/guestconfiguration" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/policy/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func dataSourcePolicyVirtualMachineConfigurationAssignment() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourcePolicyVirtualMachineConfigurationAssignmentRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "virtual_machine_name": { + Type: pluginsdk.TypeString, + Required: true, + }, + + "content_hash": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "content_uri": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "assignment_hash": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "compliance_status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "latest_report_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "last_compliance_status_checked": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourcePolicyVirtualMachineConfigurationAssignmentRead(d *pluginsdk.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + client := meta.(*clients.Client).Policy.GuestConfigurationAssignmentsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + resourceGroup := d.Get("resource_group_name").(string) + vmName := d.Get("virtual_machine_name").(string) + name := d.Get("name").(string) + + id := parse.NewVirtualMachineConfigurationAssignmentID(subscriptionId, resourceGroup, vmName, name) + + resp, err := client.Get(ctx, id.ResourceGroup, id.GuestConfigurationAssignmentName, id.VirtualMachineName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] guestConfiguration %q was not found", id.GuestConfigurationAssignmentName) + return nil + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + d.SetId(id.ID()) + + d.Set("name", id.GuestConfigurationAssignmentName) + d.Set("resource_group_name", resourceGroup) + d.Set("virtual_machine_name", vmName) + + if props := resp.Properties; props != nil { + if v := props.AssignmentHash; v != nil { + d.Set("assignment_hash", v) + } + + if v := string(props.ComplianceStatus); v != "" { + d.Set("compliance_status", v) + } + + if v := props.LatestReportID; v != nil { + d.Set("latest_report_id", v) + } + + if v := props.LastComplianceStatusChecked; v != nil { + d.Set("last_compliance_status_checked", v.Format(time.RFC3339)) + } + + contentHash, contentUri := dataSourceFlattenGuestConfigurationAssignment(props.GuestConfiguration) + + if contentHash != nil { + d.Set("content_hash", contentHash) + } + + if contentUri != nil { + d.Set("content_uri", contentUri) + } + } + return nil +} + +func dataSourceFlattenGuestConfigurationAssignment(input *guestconfiguration.Navigation) (*string, *string) { + if input == nil { + return nil, nil + } + + var contentHash *string + if input.ContentHash != nil { + contentHash = input.ContentHash + } + var contentUri *string + if input.ContentURI != nil { + contentUri = input.ContentURI + } + + return contentHash, contentUri +} diff --git a/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source_test.go b/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source_test.go new file mode 100644 index 000000000000..8c62a24f1031 --- /dev/null +++ b/internal/services/policy/policy_virtual_machine_configuration_assignment_data_source_test.go @@ -0,0 +1,159 @@ +package policy_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type PolicyVirtualMachineConfigurationAssignmentDataSource struct { +} + +func TestAccPolicyVirtualMachineConfigurationAssignmentDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_policy_virtual_machine_configuration_assignment", "test") + r := PolicyVirtualMachineConfigurationAssignmentDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("compliance_status").Exists(), + ), + }, + }) +} + +func (r PolicyVirtualMachineConfigurationAssignmentDataSource) templateBase(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +locals { + vm_name = "acctestvm%s" +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnw-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_interface" "test" { + name = "acctestnic-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} +`, data.RandomString, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func (r PolicyVirtualMachineConfigurationAssignmentDataSource) template(data acceptance.TestData) string { + tags := "" + if strings.HasPrefix(strings.ToLower(data.Client().SubscriptionID), "85b3dbca") { + tags = ` + tags = { + "azsecpack" = "nonprod" + "platformsettings.host_environment.service.platform_optedin_for_rootcerts" = "true" + } +` + } + return fmt.Sprintf(` +%s + +resource "azurerm_windows_virtual_machine" "test" { + name = local.vm_name + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + admin_password = "P@$$w0rd1234!" + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + identity { + type = "SystemAssigned" + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2016-Datacenter" + version = "latest" + } + +%s +} +`, r.templateBase(data), tags) +} + +func (r PolicyVirtualMachineConfigurationAssignmentDataSource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { + name = "AzureWindowsBaseline" + location = azurerm_windows_virtual_machine.test.location + virtual_machine_id = azurerm_windows_virtual_machine.test.id + + configuration { + assignment_type = "ApplyAndMonitor" + version = "1.*" + + parameter { + name = "Minimum Password Length;ExpectedValue" + value = "16" + } + parameter { + name = "Minimum Password Age;ExpectedValue" + value = "0" + } + parameter { + name = "Maximum Password Age;ExpectedValue" + value = "30,45" + } + parameter { + name = "Enforce Password History;ExpectedValue" + value = "10" + } + parameter { + name = "Password Must Meet Complexity Requirements;ExpectedValue" + value = "1" + } + } +} + +data "azurerm_policy_virtual_machine_configuration_assignment" "test" { + name = azurerm_policy_virtual_machine_configuration_assignment.test.name + resource_group_name = azurerm_resource_group.test.name + virtual_machine_name = azurerm_windows_virtual_machine.test.name +} +`, r.template(data)) +} diff --git a/internal/services/policy/policy_virtual_machine_configuration_assignment_resource.go b/internal/services/policy/policy_virtual_machine_configuration_assignment_resource.go index db6d636c19e2..c11da2d2c8fa 100644 --- a/internal/services/policy/policy_virtual_machine_configuration_assignment_resource.go +++ b/internal/services/policy/policy_virtual_machine_configuration_assignment_resource.go @@ -3,6 +3,7 @@ package policy import ( "fmt" "log" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/guestconfiguration/mgmt/2020-06-25/guestconfiguration" @@ -40,9 +41,10 @@ func resourcePolicyVirtualMachineConfigurationAssignment() *pluginsdk.Resource { Schema: map[string]*pluginsdk.Schema{ "name": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, }, "location": azure.SchemaLocation(), @@ -60,10 +62,11 @@ func resourcePolicyVirtualMachineConfigurationAssignment() *pluginsdk.Resource { MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ + // TODO: Remove in 3.0 "name": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, + Type: pluginsdk.TypeString, + Optional: true, + Deprecated: "This field is no longer used and will be removed in the next major version of the Azure Provider", }, "assignment_type": { @@ -80,12 +83,14 @@ func resourcePolicyVirtualMachineConfigurationAssignment() *pluginsdk.Resource { "content_hash": { Type: pluginsdk.TypeString, Optional: true, + Computed: true, ValidateFunc: validation.StringIsNotEmpty, }, "content_uri": { Type: pluginsdk.TypeString, Optional: true, + Computed: true, ValidateFunc: validation.IsURLWithScheme([]string{"http", "https"}), }, @@ -143,14 +148,27 @@ func resourcePolicyVirtualMachineConfigurationAssignmentCreateUpdate(d *pluginsd return tf.ImportAsExistsError("azurerm_policy_virtual_machine_configuration_assignment", id.ID()) } } - + guestConfiguration := expandGuestConfigurationAssignment(d.Get("configuration").([]interface{}), id.GuestConfigurationAssignmentName) parameter := guestconfiguration.Assignment{ - Name: utils.String(d.Get("name").(string)), + Name: utils.String(id.GuestConfigurationAssignmentName), Location: utils.String(location.Normalize(d.Get("location").(string))), Properties: &guestconfiguration.AssignmentProperties{ - GuestConfiguration: expandGuestConfigurationAssignment(d.Get("configuration").([]interface{})), + GuestConfiguration: guestConfiguration, }, } + + // I need to determine if the passed in guest config is a built-in config or not + // since the attribute is computed and optional I need to check the value of the + // contentURI to see if it is on a service team owned storage account or not + // all built-in guest configuration will always be on a service team owned + // storage account + if guestConfiguration.ContentURI != nil || *guestConfiguration.ContentURI != "" { + if strings.Contains(strings.ToLower(*guestConfiguration.ContentURI), "oaasguestconfig") { + parameter.Properties.GuestConfiguration.ContentHash = nil + parameter.Properties.GuestConfiguration.ContentURI = nil + } + } + if _, err := client.CreateOrUpdate(ctx, id.GuestConfigurationAssignmentName, parameter, id.ResourceGroup, id.VirtualMachineName); err != nil { return fmt.Errorf("creating/updating %s: %+v", id, err) } @@ -211,14 +229,14 @@ func resourcePolicyVirtualMachineConfigurationAssignmentDelete(d *pluginsdk.Reso return nil } -func expandGuestConfigurationAssignment(input []interface{}) *guestconfiguration.Navigation { +func expandGuestConfigurationAssignment(input []interface{}, name string) *guestconfiguration.Navigation { if len(input) == 0 { return nil } v := input[0].(map[string]interface{}) result := guestconfiguration.Navigation{ - Name: utils.String(v["name"].(string)), + Name: utils.String(name), Version: utils.String(v["version"].(string)), ConfigurationParameter: expandGuestConfigurationAssignmentConfigurationParameters(v["parameter"].(*pluginsdk.Set).List()), } @@ -255,10 +273,6 @@ func flattenGuestConfigurationAssignment(input *guestconfiguration.Navigation) [ return make([]interface{}, 0) } - var name string - if input.Name != nil { - name = *input.Name - } var version string if input.Version != nil { version = *input.Version @@ -277,7 +291,6 @@ func flattenGuestConfigurationAssignment(input *guestconfiguration.Navigation) [ } return []interface{}{ map[string]interface{}{ - "name": name, "assignment_type": string(assignmentType), "content_hash": contentHash, "content_uri": contentUri, diff --git a/internal/services/policy/policy_virtual_machine_configuration_assignment_resource_test.go b/internal/services/policy/policy_virtual_machine_configuration_assignment_resource_test.go index b69f92f52327..4a8dbfac13fb 100644 --- a/internal/services/policy/policy_virtual_machine_configuration_assignment_resource_test.go +++ b/internal/services/policy/policy_virtual_machine_configuration_assignment_resource_test.go @@ -3,6 +3,7 @@ package policy_test import ( "context" "fmt" + "strings" "testing" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" @@ -84,6 +85,10 @@ func (r PolicyVirtualMachineConfigurationAssignmentResource) Exists(ctx context. func (r PolicyVirtualMachineConfigurationAssignmentResource) templateBase(data acceptance.TestData) string { return fmt.Sprintf(` +provider "azurerm" { + features {} +} + locals { vm_name = "acctestvm%s" } @@ -122,6 +127,15 @@ resource "azurerm_network_interface" "test" { } func (r PolicyVirtualMachineConfigurationAssignmentResource) template(data acceptance.TestData) string { + tags := "" + if strings.HasPrefix(strings.ToLower(data.Client().SubscriptionID), "85b3dbca") { + tags = ` + tags = { + "azsecpack" = "nonprod" + "platformsettings.host_environment.service.platform_optedin_for_rootcerts" = "true" + } +` + } return fmt.Sprintf(` %s @@ -147,8 +161,10 @@ resource "azurerm_windows_virtual_machine" "test" { sku = "2016-Datacenter" version = "latest" } + +%s } -`, r.templateBase(data)) +`, r.templateBase(data), tags) } func (r PolicyVirtualMachineConfigurationAssignmentResource) basic(data acceptance.TestData) string { @@ -156,11 +172,12 @@ func (r PolicyVirtualMachineConfigurationAssignmentResource) basic(data acceptan %s resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { - name = "acctest-gca-%d" - location = azurerm_windows_virtual_machine.test.location + name = "WhitelistedApplication" + location = azurerm_windows_virtual_machine.test.location + virtual_machine_id = azurerm_windows_virtual_machine.test.id + configuration { - name = "WhitelistedApplication" version = "1.*" parameter { @@ -169,7 +186,7 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { } } } -`, r.template(data), data.RandomInteger) +`, r.template(data)) } func (r PolicyVirtualMachineConfigurationAssignmentResource) requiresImport(data acceptance.TestData) string { @@ -182,7 +199,6 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "import" { virtual_machine_id = azurerm_policy_virtual_machine_configuration_assignment.test.virtual_machine_id configuration { - name = "WhitelistedApplication" version = "1.*" parameter { @@ -199,12 +215,11 @@ func (r PolicyVirtualMachineConfigurationAssignmentResource) complete(data accep %s resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { - name = "acctest-gca-%d" + name = "WhitelistedApplication" location = azurerm_windows_virtual_machine.test.location virtual_machine_id = azurerm_windows_virtual_machine.test.id configuration { - name = "WhitelistedApplication" version = "1.1.1.1" assignment_type = "ApplyAndAutoCorrect" content_hash = "testcontenthash" @@ -216,7 +231,7 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { } } } -`, r.template(data), data.RandomInteger) +`, r.template(data)) } func (r PolicyVirtualMachineConfigurationAssignmentResource) updateGuestConfiguration(data acceptance.TestData) string { @@ -224,12 +239,11 @@ func (r PolicyVirtualMachineConfigurationAssignmentResource) updateGuestConfigur %s resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { - name = "acctest-gca-%d" + name = "WhitelistedApplication" location = azurerm_windows_virtual_machine.test.location virtual_machine_id = azurerm_windows_virtual_machine.test.id configuration { - name = "WhitelistedApplication" version = "1.1.1.1" assignment_type = "Audit" content_hash = "testcontenthash2" @@ -241,5 +255,5 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "test" { } } } -`, r.template(data), data.RandomInteger) +`, r.template(data)) } diff --git a/internal/services/policy/registration.go b/internal/services/policy/registration.go index abfd5c7d8db6..3f561a67c5b2 100644 --- a/internal/services/policy/registration.go +++ b/internal/services/policy/registration.go @@ -39,8 +39,9 @@ func (r Registration) WebsiteCategories() []string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ - "azurerm_policy_definition": dataSourceArmPolicyDefinition(), - "azurerm_policy_set_definition": dataSourceArmPolicySetDefinition(), + "azurerm_policy_definition": dataSourceArmPolicyDefinition(), + "azurerm_policy_set_definition": dataSourceArmPolicySetDefinition(), + "azurerm_policy_virtual_machine_configuration_assignment": dataSourcePolicyVirtualMachineConfigurationAssignment(), } } diff --git a/website/docs/d/policy_virtual_machine_configuration_assignment.html.markdown b/website/docs/d/policy_virtual_machine_configuration_assignment.html.markdown new file mode 100644 index 000000000000..05131518a3a5 --- /dev/null +++ b/website/docs/d/policy_virtual_machine_configuration_assignment.html.markdown @@ -0,0 +1,55 @@ +--- +subcategory: "Policy" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_policy_virtual_machine_configuration_assignment" +description: |- + Get information about a Guest Configuration Policy. +--- + +# Data Source: azurerm_policy_virtual_machine_configuration_assignment + +Use this data source to access information about an existing Guest Configuration Policy. + +## Example Usage + +```hcl +data "azurerm_policy_virtual_machine_configuration_assignment" "example" { + name = "AzureWindowsBaseline" + resource_group_name = "example-RG" + virtual_machine_name = "example-vm" +} + +output "compliance_status" { + value = data.azurerm_policy_virtual_machine_configuration_assignment.example.compliance_status +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Guest Configuration Assignment. + +* `resource_group_name` - (Required) Specifies the Name of the Resource Group where the Guest Configuration Assignment exists. + +* `virtual_machine_name` - (Required) Only retrieve Policy Set Definitions from this Management Group. + +## Attributes Reference + +* `id` - The ID of the Guest Configuration Assignment. + +* `content_hash` - The content hash for the Guest Configuration package. + +* `content_uri` - The content URI where the Guest Configuration package is stored. + +* `assignment_hash` - Combined hash of the configuration package and parameters. + +* `compliance_status` - A value indicating compliance status of the machine for the assigned guest configuration. Possible return values are `Compliant`, `NonCompliant` and `Pending`. + +* `last_compliance_status_checked` - Date and time, in RFC3339 format, when the machines compliance status was last checked. + +* `latest_report_id` - The ID of the latest report for the guest configuration assignment. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Guest Configuration Assignment. diff --git a/website/docs/r/policy_virtual_machine_configuration_assignment.html.markdown b/website/docs/r/policy_virtual_machine_configuration_assignment.html.markdown index 14501591173f..33269df6b2d9 100644 --- a/website/docs/r/policy_virtual_machine_configuration_assignment.html.markdown +++ b/website/docs/r/policy_virtual_machine_configuration_assignment.html.markdown @@ -3,12 +3,14 @@ subcategory: "Policy" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_policy_virtual_machine_configuration_assignment" description: |- - Applies a Configuration Policy to a Virtual Machine. + Applies a Guest Configuration Policy to a Virtual Machine. --- # azurerm_policy_virtual_machine_configuration_assignment -Applies a Configuration Policy to a Virtual Machine. +Applies a Guest Configuration Policy to a Virtual Machine. + +~> **NOTE:** You can create Guest Configuration Policies without defining a `azurerm_virtual_machine_extension` resource, however the policies will not be executed until a `azurerm_virtual_machine_extension` has been provisioned to the virtual machine. ## Example Usage @@ -85,9 +87,11 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "example" { name = "AzureWindowsBaseline" location = azurerm_windows_virtual_machine.example.location virtual_machine_id = azurerm_windows_virtual_machine.example.id + configuration { - name = "AzureWindowsBaseline" - version = "1.*" + assignment_type = "ApplyAndMonitor" + version = "1.*" + parameter { name = "Minimum Password Length;ExpectedValue" value = "16" @@ -116,7 +120,7 @@ resource "azurerm_policy_virtual_machine_configuration_assignment" "example" { The following arguments are supported: -* `name` - (Required) The name of the Policy Virtual Machine Configuration Assignment. Changing this forces a new resource to be created. +* `name` - (Required) The name of the Guest Configuration that will be assigned in this Guest Configuration Assignment. Changing this forces a new resource to be created. * `location` - (Required) The Azure location where the Policy Virtual Machine Configuration Assignment should exist. Changing this forces a new resource to be created. @@ -128,9 +132,10 @@ The following arguments are supported: --- -An `configuration` block supports the following: +A `configuration` block supports the following: -* `name` - (Required) The name of the Guest Configuration that will be assigned in this Guest Configuration Assignment. +[comment]: # (TODO: Remove in 3.0) +* `name` - (Deprecated) This field is no longer used and will be removed in the next major version of the Azure Provider. * `assignment_type` - (Optional) The assignment type for the Guest Configuration Assignment. Possible values are `Audit`, `ApplyAndAutoCorrect`, `ApplyAndMonitor` and `DeployAndAutoCorrect`. @@ -138,13 +143,15 @@ An `configuration` block supports the following: * `content_uri` - (Optional) The content URI where the Guest Configuration package is stored. +~> **NOTE:** When deploying a Custom Guest Configuration package the `content_hash` and `content_uri` fields must be defined. For Built-in Guest Configuration packages, such as the `AzureWindowsBaseline` package, the `content_hash` and `content_uri` should not be defined, rather these fields will be returned after the Built-in Guest Configuration package has been provisioned. For more information on guest configuration assignments please see the [product documentation](https://docs.microsoft.com/azure/governance/policy/concepts/guest-configuration-assignments). + * `parameter` - (Optional) One or more `parameter` blocks which define what configuration parameters and values against. * `version` - (Optional) The version of the Guest Configuration that will be assigned in this Guest Configuration Assignment. --- -An `parameter` block supports the following: +A `parameter` block supports the following: * `name` - (Required) The name of the configuration parameter to check. @@ -156,6 +163,7 @@ In addition to the Arguments listed above - the following Attributes are exporte * `id` - The ID of the Policy Virtual Machine Configuration Assignment. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: