Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support exclusions (notScopes) in azurerm_policy_assignment #2620

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions azurerm/resource_arm_policy_assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ func resourceArmPolicyAssignment() *schema.Resource {
ValidateFunc: validation.ValidateJsonString,
DiffSuppressFunc: structure.SuppressJsonDiff,
},

"not_scopes": {
Type: schema.TypeList,
Optional: true,
ForceNew: false,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just leave this out if ForceNew is false.

Suggested change
ForceNew: false,

Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}
Expand Down Expand Up @@ -137,6 +144,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
}
Expand All @@ -151,6 +163,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)
}
Expand Down Expand Up @@ -207,6 +220,8 @@ func resourceArmPolicyAssignmentRead(d *schema.ResourceData, meta interface{}) e

d.Set("parameters", json)
}

d.Set("not_scopes", props.NotScopes)
}

return nil
Expand Down Expand Up @@ -272,3 +287,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 &notScopesRes
}
88 changes: 88 additions & 0 deletions azurerm/resource_arm_policy_assignment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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 = <<POLICY_RULE
{
"if": {
"not": {
"field": "location",
"in": "[parameters('allowedLocations')]"
}
},
"then": {
"effect": "audit"
}
}
POLICY_RULE

parameters = <<PARAMETERS
{
"allowedLocations": {
"type": "Array",
"metadata": {
"description": "The list of allowed locations for resources.",
"displayName": "Allowed locations",
"strongType": "location"
}
}
}
PARAMETERS
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_policy_assignment" "test" {
name = "acctestpa-%d"
scope = "${data.azurerm_subscription.current.id}"
policy_definition_id = "${azurerm_policy_definition.test.id}"
description = "Policy Assignment created via an Acceptance Test"
not_scopes = ["${azurerm_resource_group.test.id}"]
display_name = "Acceptance Test Run %d"

parameters = <<PARAMETERS
{
"allowedLocations": {
"value": [ "%s" ]
}
}
PARAMETERS
}
`, ri, ri, ri, location, ri, ri, location)
}
2 changes: 2 additions & 0 deletions website/docs/r/policy_assignment.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ The following arguments are supported:

~> **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:
Expand Down