Skip to content

Commit

Permalink
Merge pull request #925 from terraform-providers/application-security…
Browse files Browse the repository at this point in the history
…-group-rules

Adding support for connecting Network Security Rules to Application Security Groups
  • Loading branch information
tombuildsstuff authored Mar 2, 2018
2 parents a6730d1 + 4c02103 commit 0c43b73
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 4 deletions.
14 changes: 14 additions & 0 deletions azurerm/data_source_network_security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ func dataSourceArmNetworkSecurityGroup() *schema.Resource {
Set: schema.HashString,
},

"source_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"destination_address_prefix": {
Type: schema.TypeString,
Computed: true,
Expand All @@ -88,6 +95,13 @@ func dataSourceArmNetworkSecurityGroup() *schema.Resource {
Set: schema.HashString,
},

"destination_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"access": {
Type: schema.TypeString,
Computed: true,
Expand Down
7 changes: 3 additions & 4 deletions azurerm/import_arm_network_security_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ func TestAccAzureRMNetworkSecurityRule_importBasic(t *testing.T) {
Config: testAccAzureRMNetworkSecurityRule_basic(rInt, testLocation()),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"network_security_group_name"},
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
Expand Down
54 changes: 54 additions & 0 deletions azurerm/resource_arm_network_security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ func resourceArmNetworkSecurityGroup() *schema.Resource {
Set: schema.HashString,
},

"destination_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"source_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"access": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -324,6 +338,28 @@ func expandAzureRmSecurityRules(d *schema.ResourceData) ([]network.SecurityRule,
properties.DestinationAddressPrefixes = &destinationAddressPrefixes
}

if r, ok := sgRule["source_application_security_group_ids"].(*schema.Set); ok && r.Len() > 0 {
var sourceApplicationSecurityGroups []network.ApplicationSecurityGroup
for _, v := range r.List() {
sg := network.ApplicationSecurityGroup{
ID: utils.String(v.(string)),
}
sourceApplicationSecurityGroups = append(sourceApplicationSecurityGroups, sg)
}
properties.SourceApplicationSecurityGroups = &sourceApplicationSecurityGroups
}

if r, ok := sgRule["destination_application_security_group_ids"].(*schema.Set); ok && r.Len() > 0 {
var destinationApplicationSecurityGroups []network.ApplicationSecurityGroup
for _, v := range r.List() {
sg := network.ApplicationSecurityGroup{
ID: utils.String(v.(string)),
}
destinationApplicationSecurityGroups = append(destinationApplicationSecurityGroups, sg)
}
properties.DestinationApplicationSecurityGroups = &destinationApplicationSecurityGroups
}

rules = append(rules, network.SecurityRule{
Name: &name,
SecurityRulePropertiesFormat: &properties,
Expand Down Expand Up @@ -358,12 +394,30 @@ func flattenNetworkSecurityRules(rules *[]network.SecurityRule) []map[string]int
if props.DestinationPortRanges != nil {
sgRule["destination_port_ranges"] = sliceToSet(*props.DestinationPortRanges)
}

destinationApplicationSecurityGroups := make([]string, 0)
if props.DestinationApplicationSecurityGroups != nil {
for _, g := range *props.DestinationApplicationSecurityGroups {
destinationApplicationSecurityGroups = append(destinationApplicationSecurityGroups, *g.ID)
}
}
sgRule["destination_application_security_group_ids"] = sliceToSet(destinationApplicationSecurityGroups)

if props.SourceAddressPrefix != nil {
sgRule["source_address_prefix"] = *props.SourceAddressPrefix
}
if props.SourceAddressPrefixes != nil {
sgRule["source_address_prefixes"] = sliceToSet(*props.SourceAddressPrefixes)
}

sourceApplicationSecurityGroups := make([]string, 0)
if props.SourceApplicationSecurityGroups != nil {
for _, g := range *props.SourceApplicationSecurityGroups {
sourceApplicationSecurityGroups = append(sourceApplicationSecurityGroups, *g.ID)
}
}
sgRule["source_application_security_group_ids"] = sliceToSet(sourceApplicationSecurityGroups)

if props.SourcePortRange != nil {
sgRule["source_port_range"] = *props.SourcePortRange
}
Expand Down
58 changes: 58 additions & 0 deletions azurerm/resource_arm_network_security_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,25 @@ func TestAccAzureRMNetworkSecurityGroup_augmented(t *testing.T) {
})
}

func TestAccAzureRMNetworkSecurityGroup_applicationSecurityGroup(t *testing.T) {
resourceName := "azurerm_network_security_group.test"
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMNetworkSecurityGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMNetworkSecurityGroup_applicationSecurityGroup(rInt, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMNetworkSecurityGroupExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "security_rule.#", "1"),
),
},
},
})
}

func testCheckAzureRMNetworkSecurityGroupExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {

Expand Down Expand Up @@ -423,3 +442,42 @@ resource "azurerm_network_security_group" "test" {
}
`, rInt, location)
}

func testAccAzureRMNetworkSecurityGroup_applicationSecurityGroup(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_application_security_group" "first" {
name = "acctest-first%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_application_security_group" "second" {
name = "acctest-second%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_network_security_group" "test" {
name = "acctestnsg-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
security_rule {
name = "test123"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_application_security_group_ids = ["${azurerm_application_security_group.first.id}"]
destination_application_security_group_ids = ["${azurerm_application_security_group.second.id}"]
source_port_ranges = [ "10000-40000" ]
destination_port_ranges = [ "80", "443", "8080", "8190" ]
}
}
`, rInt, location, rInt, rInt, rInt)
}
37 changes: 37 additions & 0 deletions azurerm/resource_arm_network_security_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ func resourceArmNetworkSecurityRule() *schema.Resource {
ConflictsWith: []string{"destination_address_prefix"},
},

"source_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"destination_application_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"access": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -215,6 +229,28 @@ func resourceArmNetworkSecurityRuleCreate(d *schema.ResourceData, meta interface
rule.SecurityRulePropertiesFormat.DestinationAddressPrefixes = &destinationAddressPrefixes
}

if r, ok := d.GetOk("source_application_security_group_ids"); ok {
var sourceApplicationSecurityGroups []network.ApplicationSecurityGroup
for _, v := range r.(*schema.Set).List() {
sg := network.ApplicationSecurityGroup{
ID: utils.String(v.(string)),
}
sourceApplicationSecurityGroups = append(sourceApplicationSecurityGroups, sg)
}
rule.SourceApplicationSecurityGroups = &sourceApplicationSecurityGroups
}

if r, ok := d.GetOk("destination_application_security_group_ids"); ok {
var destinationApplicationSecurityGroups []network.ApplicationSecurityGroup
for _, v := range r.(*schema.Set).List() {
sg := network.ApplicationSecurityGroup{
ID: utils.String(v.(string)),
}
destinationApplicationSecurityGroups = append(destinationApplicationSecurityGroups, sg)
}
rule.DestinationApplicationSecurityGroups = &destinationApplicationSecurityGroups
}

future, err := client.CreateOrUpdate(ctx, resGroup, nsgName, name, rule)
if err != nil {
return fmt.Errorf("Error Creating/Updating Network Security Rule %q (NSG %q / Resource Group %q): %+v", name, nsgName, resGroup, err)
Expand Down Expand Up @@ -261,6 +297,7 @@ func resourceArmNetworkSecurityRuleRead(d *schema.ResourceData, meta interface{}

d.Set("name", resp.Name)
d.Set("resource_group_name", resGroup)
d.Set("network_security_group_name", networkSGName)

if props := resp.SecurityRulePropertiesFormat; props != nil {
d.Set("description", props.Description)
Expand Down
58 changes: 58 additions & 0 deletions azurerm/resource_arm_network_security_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ func TestAccAzureRMNetworkSecurityRule_augmented(t *testing.T) {
})
}

func TestAccAzureRMNetworkSecurityRule_applicationSecurityGroups(t *testing.T) {
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMNetworkSecurityRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMNetworkSecurityRule_applicationSecurityGroups(rInt, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMNetworkSecurityRuleExists("azurerm_network_security_rule.test1"),
),
},
},
})
}

func testCheckAzureRMNetworkSecurityRuleExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {

Expand Down Expand Up @@ -307,3 +324,44 @@ resource "azurerm_network_security_rule" "test1" {
}
`, rInt, location)
}

func testAccAzureRMNetworkSecurityRule_applicationSecurityGroups(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_application_security_group" "first" {
name = "acctest-first%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_application_security_group" "second" {
name = "acctest-second%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_network_security_group" "test" {
name = "acctestnsg-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_network_security_rule" "test1" {
name = "test123"
resource_group_name = "${azurerm_resource_group.test.name}"
network_security_group_name = "${azurerm_network_security_group.test.name}"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_application_security_group_ids = ["${azurerm_application_security_group.first.id}"]
destination_application_security_group_ids = ["${azurerm_application_security_group.second.id}"]
source_port_ranges = [ "10000-40000" ]
destination_port_ranges = [ "80", "443", "8080", "8190" ]
}
`, rInt, location, rInt, rInt, rInt)
}
4 changes: 4 additions & 0 deletions website/docs/d/network_security_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ The `security_rule` block supports:

* `destination_address_prefix` - CIDR or destination IP range or * to match any IP.

* `source_application_security_group_ids` - A List of source Application Security Group ID's

* `destination_application_security_group_ids` - A List of destination Application Security Group ID's

* `access` - Is network traffic is allowed or denied?

* `priority` - The priority of the rule
Expand Down
4 changes: 4 additions & 0 deletions website/docs/r/network_security_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,14 @@ The `security_rule` block supports:

* `source_address_prefixes` - (Optional) List of source address prefixes. Tags may not be used. This is required if `source_address_prefix` is not specified.

* `source_application_security_group_ids` - (Optional) A List of source Application Security Group ID's

* `destination_address_prefix` - (Optional) CIDR or destination IP range or * to match any IP. Tags such as ‘VirtualNetwork’, ‘AzureLoadBalancer’ and ‘Internet’ can also be used. This is required if `destination_address_prefixes` is not specified.

* `destination_address_prefixes` - (Optional) List of destination address prefixes. Tags may not be used. This is required if `destination_address_prefix` is not specified.

* `destination_application_security_group_ids` - (Optional) A List of destination Application Security Group ID's

* `access` - (Required) Specifies whether network traffic is allowed or denied. Possible values are `Allow` and `Deny`.

* `priority` - (Required) Specifies the priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule.
Expand Down
4 changes: 4 additions & 0 deletions website/docs/r/network_security_rule.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@ The following arguments are supported:

* `source_address_prefixes` - (Optional) List of source address prefixes. Tags may not be used. This is required if `source_address_prefix` is not specified.

* `source_application_security_group_ids` - (Optional) A List of source Application Security Group ID's

* `destination_address_prefix` - (Optional) CIDR or destination IP range or * to match any IP. Tags such as ‘VirtualNetwork’, ‘AzureLoadBalancer’ and ‘Internet’ can also be used. This is required if `destination_address_prefixes` is not specified.

* `destination_address_prefixes` - (Optional) List of destination address prefixes. Tags may not be used. This is required if `destination_address_prefix` is not specified.

* `destination_application_security_group_ids` - (Optional) A List of destination Application Security Group ID's

* `access` - (Required) Specifies whether network traffic is allowed or denied. Possible values are `Allow` and `Deny`.

* `priority` - (Required) Specifies the priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule.
Expand Down

0 comments on commit 0c43b73

Please sign in to comment.