diff --git a/azurerm/resource_arm_policy_assignment.go b/azurerm/resource_arm_policy_assignment.go index 535bc4c97767..07eae1e523a8 100644 --- a/azurerm/resource_arm_policy_assignment.go +++ b/azurerm/resource_arm_policy_assignment.go @@ -93,6 +93,12 @@ func resourceArmPolicyAssignment() *schema.Resource { ValidateFunc: validation.ValidateJsonString, DiffSuppressFunc: structure.SuppressJsonDiff, }, + + "not_scopes": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, } } @@ -137,6 +143,11 @@ func resourceArmPolicyAssignmentCreateOrUpdate(d *schema.ResourceData, meta inte assignment.AssignmentProperties.Parameters = &expandedParams } + if _, ok := d.GetOk("not_scopes"); ok { + notScopes := expandAzureRmPolicyNotScopes(d) + assignment.AssignmentProperties.NotScopes = notScopes + } + if _, err := client.Create(ctx, scope, name, assignment); err != nil { return err } @@ -151,6 +162,7 @@ func resourceArmPolicyAssignmentCreateOrUpdate(d *schema.ResourceData, meta inte MinTimeout: 10 * time.Second, ContinuousTargetOccurence: 10, } + if _, err := stateConf.WaitForState(); err != nil { return fmt.Errorf("Error waiting for Policy Assignment %q to become available: %s", name, err) } @@ -207,6 +219,8 @@ func resourceArmPolicyAssignmentRead(d *schema.ResourceData, meta interface{}) e d.Set("parameters", json) } + + d.Set("not_scopes", props.NotScopes) } return nil @@ -272,3 +286,14 @@ func flattenAzureRmPolicyIdentity(identity *policy.Identity) []interface{} { return []interface{}{result} } + +func expandAzureRmPolicyNotScopes(d *schema.ResourceData) *[]string { + notScopes := d.Get("not_scopes").([]interface{}) + notScopesRes := make([]string, 0) + + for _, notScope := range notScopes { + notScopesRes = append(notScopesRes, notScope.(string)) + } + + return ¬ScopesRes +} diff --git a/azurerm/resource_arm_policy_assignment_test.go b/azurerm/resource_arm_policy_assignment_test.go index 7e18fadc3e0a..230602928d61 100644 --- a/azurerm/resource_arm_policy_assignment_test.go +++ b/azurerm/resource_arm_policy_assignment_test.go @@ -88,6 +88,32 @@ func TestAccAzureRMPolicyAssignment_complete(t *testing.T) { }) } +func TestAccAzureRMPolicyAssignment_not_scopes(t *testing.T) { + resourceName := "azurerm_policy_assignment.test" + + ri := acctest.RandInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMPolicyAssignmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAzureRMPolicyAssignment_not_scopes(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMPolicyAssignmentExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMPolicyAssignmentExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -306,3 +332,65 @@ PARAMETERS } `, ri, ri, ri, location, ri, ri, location) } + +func testAzureRMPolicyAssignment_not_scopes(ri int, location string) string { + return fmt.Sprintf(` +data "azurerm_subscription" "current" {} + +resource "azurerm_policy_definition" "test" { + name = "acctestpol-%d" + policy_type = "Custom" + mode = "All" + display_name = "acctestpol-%d" + + policy_rule = < **NOTE:** This value is required when the specified Policy Definition contains the `parameters` field. +* `not_scopes` - (Optional) A list of the Policy Assignment's excluded scopes. The list must contain Resource IDs (such as Subscriptions e.g. `/subscriptions/00000000-0000-0000-000000000000` or Resource Groups e.g.`/subscriptions/00000000-0000-0000-000000000000/resourceGroups/myResourceGroup`). + --- An `identity` block supports the following: