github.com/akazakov/terraform@v0.5.2-0.20160205142716-097441beafdf/builtin/providers/aws/resource_aws_security_group_rule_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"testing"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/aws/awserr"
    11  	"github.com/aws/aws-sdk-go/service/ec2"
    12  	"github.com/hashicorp/terraform/helper/acctest"
    13  	"github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/terraform"
    15  )
    16  
    17  func TestIpPermissionIDHash(t *testing.T) {
    18  	simple := &ec2.IpPermission{
    19  		IpProtocol: aws.String("tcp"),
    20  		FromPort:   aws.Int64(int64(80)),
    21  		ToPort:     aws.Int64(int64(8000)),
    22  		IpRanges: []*ec2.IpRange{
    23  			&ec2.IpRange{
    24  				CidrIp: aws.String("10.0.0.0/8"),
    25  			},
    26  		},
    27  	}
    28  
    29  	egress := &ec2.IpPermission{
    30  		IpProtocol: aws.String("tcp"),
    31  		FromPort:   aws.Int64(int64(80)),
    32  		ToPort:     aws.Int64(int64(8000)),
    33  		IpRanges: []*ec2.IpRange{
    34  			&ec2.IpRange{
    35  				CidrIp: aws.String("10.0.0.0/8"),
    36  			},
    37  		},
    38  	}
    39  
    40  	egress_all := &ec2.IpPermission{
    41  		IpProtocol: aws.String("-1"),
    42  		IpRanges: []*ec2.IpRange{
    43  			&ec2.IpRange{
    44  				CidrIp: aws.String("10.0.0.0/8"),
    45  			},
    46  		},
    47  	}
    48  
    49  	vpc_security_group_source := &ec2.IpPermission{
    50  		IpProtocol: aws.String("tcp"),
    51  		FromPort:   aws.Int64(int64(80)),
    52  		ToPort:     aws.Int64(int64(8000)),
    53  		UserIdGroupPairs: []*ec2.UserIdGroupPair{
    54  			&ec2.UserIdGroupPair{
    55  				UserId:  aws.String("987654321"),
    56  				GroupId: aws.String("sg-12345678"),
    57  			},
    58  			&ec2.UserIdGroupPair{
    59  				UserId:  aws.String("123456789"),
    60  				GroupId: aws.String("sg-987654321"),
    61  			},
    62  			&ec2.UserIdGroupPair{
    63  				UserId:  aws.String("123456789"),
    64  				GroupId: aws.String("sg-12345678"),
    65  			},
    66  		},
    67  	}
    68  
    69  	security_group_source := &ec2.IpPermission{
    70  		IpProtocol: aws.String("tcp"),
    71  		FromPort:   aws.Int64(int64(80)),
    72  		ToPort:     aws.Int64(int64(8000)),
    73  		UserIdGroupPairs: []*ec2.UserIdGroupPair{
    74  			&ec2.UserIdGroupPair{
    75  				UserId:    aws.String("987654321"),
    76  				GroupName: aws.String("my-security-group"),
    77  			},
    78  			&ec2.UserIdGroupPair{
    79  				UserId:    aws.String("123456789"),
    80  				GroupName: aws.String("my-security-group"),
    81  			},
    82  			&ec2.UserIdGroupPair{
    83  				UserId:    aws.String("123456789"),
    84  				GroupName: aws.String("my-other-security-group"),
    85  			},
    86  		},
    87  	}
    88  
    89  	// hardcoded hashes, to detect future change
    90  	cases := []struct {
    91  		Input  *ec2.IpPermission
    92  		Type   string
    93  		Output string
    94  	}{
    95  		{simple, "ingress", "sgrule-3403497314"},
    96  		{egress, "egress", "sgrule-1173186295"},
    97  		{egress_all, "egress", "sgrule-766323498"},
    98  		{vpc_security_group_source, "egress", "sgrule-351225364"},
    99  		{security_group_source, "egress", "sgrule-2198807188"},
   100  	}
   101  
   102  	for _, tc := range cases {
   103  		actual := ipPermissionIDHash("sg-12345", tc.Type, tc.Input)
   104  		if actual != tc.Output {
   105  			t.Errorf("input: %s - %s\noutput: %s", tc.Type, tc.Input, actual)
   106  		}
   107  	}
   108  }
   109  
   110  func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) {
   111  	var group ec2.SecurityGroup
   112  
   113  	testRuleCount := func(*terraform.State) error {
   114  		if len(group.IpPermissions) != 1 {
   115  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   116  				1, len(group.IpPermissions))
   117  		}
   118  
   119  		rule := group.IpPermissions[0]
   120  		if *rule.FromPort != int64(80) {
   121  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   122  				80, int(*rule.FromPort))
   123  		}
   124  
   125  		return nil
   126  	}
   127  
   128  	resource.Test(t, resource.TestCase{
   129  		PreCheck:     func() { testAccPreCheck(t) },
   130  		Providers:    testAccProviders,
   131  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   132  		Steps: []resource.TestStep{
   133  			resource.TestStep{
   134  				Config: testAccAWSSecurityGroupRuleIngressConfig,
   135  				Check: resource.ComposeTestCheckFunc(
   136  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   137  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   138  					resource.TestCheckResourceAttr(
   139  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   140  					testRuleCount,
   141  				),
   142  			},
   143  		},
   144  	})
   145  }
   146  
   147  func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
   148  	var group ec2.SecurityGroup
   149  
   150  	testRuleCount := func(*terraform.State) error {
   151  		if len(group.IpPermissions) != 1 {
   152  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   153  				1, len(group.IpPermissions))
   154  		}
   155  
   156  		rule := group.IpPermissions[0]
   157  		if *rule.FromPort != int64(80) {
   158  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   159  				80, int(*rule.FromPort))
   160  		}
   161  
   162  		return nil
   163  	}
   164  
   165  	resource.Test(t, resource.TestCase{
   166  		PreCheck:     func() { testAccPreCheck(t) },
   167  		Providers:    testAccProviders,
   168  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   169  		Steps: []resource.TestStep{
   170  			resource.TestStep{
   171  				Config: testAccAWSSecurityGroupRuleIngressClassicConfig,
   172  				Check: resource.ComposeTestCheckFunc(
   173  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   174  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   175  					resource.TestCheckResourceAttr(
   176  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   177  					testRuleCount,
   178  				),
   179  			},
   180  		},
   181  	})
   182  }
   183  
   184  func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) {
   185  	var group ec2.SecurityGroup
   186  
   187  	testMultiRuleCount := func(*terraform.State) error {
   188  		if len(group.IpPermissions) != 2 {
   189  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   190  				2, len(group.IpPermissions))
   191  		}
   192  
   193  		var rule *ec2.IpPermission
   194  		for _, r := range group.IpPermissions {
   195  			if *r.FromPort == int64(80) {
   196  				rule = r
   197  			}
   198  		}
   199  
   200  		if *rule.ToPort != int64(8000) {
   201  			return fmt.Errorf("Wrong Security Group port 2 setting, expected %d, got %d",
   202  				8000, int(*rule.ToPort))
   203  		}
   204  
   205  		return nil
   206  	}
   207  
   208  	resource.Test(t, resource.TestCase{
   209  		PreCheck:     func() { testAccPreCheck(t) },
   210  		Providers:    testAccProviders,
   211  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   212  		Steps: []resource.TestStep{
   213  			resource.TestStep{
   214  				Config: testAccAWSSecurityGroupRuleConfigMultiIngress,
   215  				Check: resource.ComposeTestCheckFunc(
   216  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   217  					testMultiRuleCount,
   218  				),
   219  			},
   220  		},
   221  	})
   222  }
   223  
   224  func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
   225  	var group ec2.SecurityGroup
   226  
   227  	resource.Test(t, resource.TestCase{
   228  		PreCheck:     func() { testAccPreCheck(t) },
   229  		Providers:    testAccProviders,
   230  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   231  		Steps: []resource.TestStep{
   232  			resource.TestStep{
   233  				Config: testAccAWSSecurityGroupRuleEgressConfig,
   234  				Check: resource.ComposeTestCheckFunc(
   235  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   236  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"),
   237  				),
   238  			},
   239  		},
   240  	})
   241  }
   242  
   243  func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) {
   244  	var group ec2.SecurityGroup
   245  
   246  	resource.Test(t, resource.TestCase{
   247  		PreCheck:     func() { testAccPreCheck(t) },
   248  		Providers:    testAccProviders,
   249  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   250  		Steps: []resource.TestStep{
   251  			resource.TestStep{
   252  				Config: testAccAWSSecurityGroupRuleConfigSelfReference,
   253  				Check: resource.ComposeTestCheckFunc(
   254  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   255  				),
   256  			},
   257  		},
   258  	})
   259  }
   260  
   261  // testing partial match implementation
   262  func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
   263  	var group ec2.SecurityGroup
   264  
   265  	p := ec2.IpPermission{
   266  		FromPort:   aws.Int64(80),
   267  		ToPort:     aws.Int64(80),
   268  		IpProtocol: aws.String("tcp"),
   269  		IpRanges: []*ec2.IpRange{
   270  			&ec2.IpRange{CidrIp: aws.String("10.0.2.0/24")},
   271  			&ec2.IpRange{CidrIp: aws.String("10.0.3.0/24")},
   272  			&ec2.IpRange{CidrIp: aws.String("10.0.4.0/24")},
   273  		},
   274  	}
   275  
   276  	o := ec2.IpPermission{
   277  		FromPort:   aws.Int64(80),
   278  		ToPort:     aws.Int64(80),
   279  		IpProtocol: aws.String("tcp"),
   280  		IpRanges: []*ec2.IpRange{
   281  			&ec2.IpRange{CidrIp: aws.String("10.0.5.0/24")},
   282  		},
   283  	}
   284  
   285  	resource.Test(t, resource.TestCase{
   286  		PreCheck:     func() { testAccPreCheck(t) },
   287  		Providers:    testAccProviders,
   288  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   289  		Steps: []resource.TestStep{
   290  			resource.TestStep{
   291  				Config: testAccAWSSecurityGroupRulePartialMatching,
   292  				Check: resource.ComposeTestCheckFunc(
   293  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   294  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"),
   295  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.other", &group, &o, "ingress"),
   296  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"),
   297  				),
   298  			},
   299  		},
   300  	})
   301  }
   302  
   303  func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
   304  	var group ec2.SecurityGroup
   305  	var nat ec2.SecurityGroup
   306  	var p ec2.IpPermission
   307  
   308  	// This function creates the expected IPPermission with the group id from an
   309  	// external security group, needed because Security Group IDs are generated on
   310  	// AWS side and can't be known ahead of time.
   311  	setupSG := func(*terraform.State) error {
   312  		if nat.GroupId == nil {
   313  			return fmt.Errorf("Error: nat group has nil GroupID")
   314  		}
   315  
   316  		p = ec2.IpPermission{
   317  			FromPort:   aws.Int64(80),
   318  			ToPort:     aws.Int64(80),
   319  			IpProtocol: aws.String("tcp"),
   320  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   321  				&ec2.UserIdGroupPair{GroupId: nat.GroupId},
   322  			},
   323  		}
   324  
   325  		return nil
   326  	}
   327  
   328  	resource.Test(t, resource.TestCase{
   329  		PreCheck:     func() { testAccPreCheck(t) },
   330  		Providers:    testAccProviders,
   331  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   332  		Steps: []resource.TestStep{
   333  			resource.TestStep{
   334  				Config: testAccAWSSecurityGroupRulePartialMatching_Source,
   335  				Check: resource.ComposeTestCheckFunc(
   336  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   337  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat),
   338  					setupSG,
   339  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"),
   340  				),
   341  			},
   342  		},
   343  	})
   344  }
   345  
   346  func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
   347  	var group ec2.SecurityGroup
   348  
   349  	resource.Test(t, resource.TestCase{
   350  		PreCheck:     func() { testAccPreCheck(t) },
   351  		Providers:    testAccProviders,
   352  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   353  		Steps: []resource.TestStep{
   354  			resource.TestStep{
   355  				Config: testAccAWSSecurityGroupRuleRace,
   356  				Check: resource.ComposeTestCheckFunc(
   357  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group),
   358  				),
   359  			},
   360  		},
   361  	})
   362  }
   363  
   364  func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
   365  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   366  
   367  	for _, rs := range s.RootModule().Resources {
   368  		if rs.Type != "aws_security_group" {
   369  			continue
   370  		}
   371  
   372  		// Retrieve our group
   373  		req := &ec2.DescribeSecurityGroupsInput{
   374  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   375  		}
   376  		resp, err := conn.DescribeSecurityGroups(req)
   377  		if err == nil {
   378  			if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   379  				return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
   380  			}
   381  
   382  			return nil
   383  		}
   384  
   385  		ec2err, ok := err.(awserr.Error)
   386  		if !ok {
   387  			return err
   388  		}
   389  		// Confirm error code is what we want
   390  		if ec2err.Code() != "InvalidGroup.NotFound" {
   391  			return err
   392  		}
   393  	}
   394  
   395  	return nil
   396  }
   397  
   398  func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
   399  	return func(s *terraform.State) error {
   400  		rs, ok := s.RootModule().Resources[n]
   401  		if !ok {
   402  			return fmt.Errorf("Not found: %s", n)
   403  		}
   404  
   405  		if rs.Primary.ID == "" {
   406  			return fmt.Errorf("No Security Group is set")
   407  		}
   408  
   409  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   410  		req := &ec2.DescribeSecurityGroupsInput{
   411  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   412  		}
   413  		resp, err := conn.DescribeSecurityGroups(req)
   414  		if err != nil {
   415  			return err
   416  		}
   417  
   418  		if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   419  			*group = *resp.SecurityGroups[0]
   420  			return nil
   421  		}
   422  
   423  		return fmt.Errorf("Security Group not found")
   424  	}
   425  }
   426  
   427  func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
   428  	return func(s *terraform.State) error {
   429  		rs, ok := s.RootModule().Resources[n]
   430  		if !ok {
   431  			return fmt.Errorf("Security Group Rule Not found: %s", n)
   432  		}
   433  
   434  		if rs.Primary.ID == "" {
   435  			return fmt.Errorf("No Security Group Rule is set")
   436  		}
   437  
   438  		if p == nil {
   439  			p = &ec2.IpPermission{
   440  				FromPort:   aws.Int64(80),
   441  				ToPort:     aws.Int64(8000),
   442  				IpProtocol: aws.String("tcp"),
   443  				IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("10.0.0.0/8")}},
   444  			}
   445  		}
   446  
   447  		var matchingRule *ec2.IpPermission
   448  		var rules []*ec2.IpPermission
   449  		if ruleType == "ingress" {
   450  			rules = group.IpPermissions
   451  		} else {
   452  			rules = group.IpPermissionsEgress
   453  		}
   454  
   455  		if len(rules) == 0 {
   456  			return fmt.Errorf("No IPPerms")
   457  		}
   458  
   459  		for _, r := range rules {
   460  			if r.ToPort != nil && *p.ToPort != *r.ToPort {
   461  				continue
   462  			}
   463  
   464  			if r.FromPort != nil && *p.FromPort != *r.FromPort {
   465  				continue
   466  			}
   467  
   468  			if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
   469  				continue
   470  			}
   471  
   472  			remaining := len(p.IpRanges)
   473  			for _, ip := range p.IpRanges {
   474  				for _, rip := range r.IpRanges {
   475  					if *ip.CidrIp == *rip.CidrIp {
   476  						remaining--
   477  					}
   478  				}
   479  			}
   480  
   481  			if remaining > 0 {
   482  				continue
   483  			}
   484  
   485  			remaining = len(p.UserIdGroupPairs)
   486  			for _, ip := range p.UserIdGroupPairs {
   487  				for _, rip := range r.UserIdGroupPairs {
   488  					if *ip.GroupId == *rip.GroupId {
   489  						remaining--
   490  					}
   491  				}
   492  			}
   493  
   494  			if remaining > 0 {
   495  				continue
   496  			}
   497  			matchingRule = r
   498  		}
   499  
   500  		if matchingRule != nil {
   501  			log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
   502  			return nil
   503  		}
   504  
   505  		return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
   506  	}
   507  }
   508  
   509  const testAccAWSSecurityGroupRuleIngressConfig = `
   510  resource "aws_security_group" "web" {
   511    name = "terraform_acceptance_test_example"
   512    description = "Used in the terraform acceptance tests"
   513  
   514          tags {
   515                  Name = "tf-acc-test"
   516          }
   517  }
   518  
   519  resource "aws_security_group_rule" "ingress_1" {
   520    type = "ingress"
   521    protocol = "tcp"
   522    from_port = 80
   523    to_port = 8000
   524    cidr_blocks = ["10.0.0.0/8"]
   525  
   526    security_group_id = "${aws_security_group.web.id}"
   527  }
   528  `
   529  
   530  const testAccAWSSecurityGroupRuleIngressClassicConfig = `
   531  provider "aws" {
   532          region = "us-east-1"
   533  }
   534  
   535  resource "aws_security_group" "web" {
   536    name = "terraform_acceptance_test_example"
   537    description = "Used in the terraform acceptance tests"
   538  
   539          tags {
   540                  Name = "tf-acc-test"
   541          }
   542  }
   543  
   544  resource "aws_security_group_rule" "ingress_1" {
   545    type = "ingress"
   546    protocol = "tcp"
   547    from_port = 80
   548    to_port = 8000
   549    cidr_blocks = ["10.0.0.0/8"]
   550  
   551    security_group_id = "${aws_security_group.web.id}"
   552  }
   553  `
   554  
   555  const testAccAWSSecurityGroupRuleEgressConfig = `
   556  resource "aws_security_group" "web" {
   557    name = "terraform_acceptance_test_example"
   558    description = "Used in the terraform acceptance tests"
   559  
   560          tags {
   561                  Name = "tf-acc-test"
   562          }
   563  }
   564  
   565  resource "aws_security_group_rule" "egress_1" {
   566    type = "egress"
   567    protocol = "tcp"
   568    from_port = 80
   569    to_port = 8000
   570    cidr_blocks = ["10.0.0.0/8"]
   571  
   572    security_group_id = "${aws_security_group.web.id}"
   573  }
   574  `
   575  
   576  const testAccAWSSecurityGroupRuleConfigMultiIngress = `
   577  resource "aws_security_group" "web" {
   578    name = "terraform_acceptance_test_example_2"
   579    description = "Used in the terraform acceptance tests"
   580  }
   581  
   582  resource "aws_security_group" "worker" {
   583    name = "terraform_acceptance_test_example_worker"
   584    description = "Used in the terraform acceptance tests"
   585  }
   586  
   587  
   588  resource "aws_security_group_rule" "ingress_1" {
   589    type = "ingress"
   590    protocol = "tcp"
   591    from_port = 22
   592    to_port = 22
   593    cidr_blocks = ["10.0.0.0/8"]
   594  
   595    security_group_id = "${aws_security_group.web.id}"
   596  }
   597  
   598  resource "aws_security_group_rule" "ingress_2" {
   599    type = "ingress"
   600    protocol = "tcp"
   601    from_port = 80
   602    to_port = 8000
   603          self = true
   604  
   605    security_group_id = "${aws_security_group.web.id}"
   606  }
   607  `
   608  
   609  // check for GH-1985 regression
   610  const testAccAWSSecurityGroupRuleConfigSelfReference = `
   611  provider "aws" {
   612    region = "us-west-2"
   613  }
   614  
   615  resource "aws_vpc" "main" {
   616    cidr_block = "10.0.0.0/16"
   617    tags {
   618      Name = "sg-self-test"
   619    }
   620  }
   621  
   622  resource "aws_security_group" "web" {
   623    name = "main"
   624    vpc_id = "${aws_vpc.main.id}"
   625    tags {
   626      Name = "sg-self-test"
   627    }
   628  }
   629  
   630  resource "aws_security_group_rule" "self" {
   631    type = "ingress"
   632    protocol = "-1"
   633    from_port = 0
   634    to_port = 0
   635    self = true
   636    security_group_id = "${aws_security_group.web.id}"
   637  }
   638  `
   639  
   640  const testAccAWSSecurityGroupRulePartialMatching = `
   641  resource "aws_vpc" "default" {
   642    cidr_block = "10.0.0.0/16"
   643    tags {
   644      Name = "tf-sg-rule-bug"
   645    }
   646  }
   647  
   648  resource "aws_security_group" "web" {
   649      name = "tf-other"
   650      vpc_id = "${aws_vpc.default.id}"
   651      tags {
   652          Name        = "tf-other-sg"
   653      }
   654  }
   655  
   656  resource "aws_security_group" "nat" {
   657      name = "tf-nat"
   658      vpc_id = "${aws_vpc.default.id}"
   659      tags {
   660          Name        = "tf-nat-sg"
   661      }
   662  }
   663  
   664  resource "aws_security_group_rule" "ingress" {
   665      type        = "ingress"
   666      from_port   = 80
   667      to_port     = 80
   668      protocol    = "tcp"
   669      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   670  
   671     security_group_id = "${aws_security_group.web.id}"
   672  }
   673  
   674  resource "aws_security_group_rule" "other" {
   675      type        = "ingress"
   676      from_port   = 80
   677      to_port     = 80
   678      protocol    = "tcp"
   679      cidr_blocks = ["10.0.5.0/24"]
   680  
   681     security_group_id = "${aws_security_group.web.id}"
   682  }
   683  
   684  // same a above, but different group, to guard against bad hashing
   685  resource "aws_security_group_rule" "nat_ingress" {
   686      type        = "ingress"
   687      from_port   = 80
   688      to_port     = 80
   689      protocol    = "tcp"
   690      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   691  
   692     security_group_id = "${aws_security_group.nat.id}"
   693  }
   694  `
   695  
   696  const testAccAWSSecurityGroupRulePartialMatching_Source = `
   697  resource "aws_vpc" "default" {
   698    cidr_block = "10.0.0.0/16"
   699    tags {
   700      Name = "tf-sg-rule-bug"
   701    }
   702  }
   703  
   704  resource "aws_security_group" "web" {
   705      name = "tf-other"
   706      vpc_id = "${aws_vpc.default.id}"
   707      tags {
   708          Name        = "tf-other-sg"
   709      }
   710  }
   711  
   712  resource "aws_security_group" "nat" {
   713      name = "tf-nat"
   714      vpc_id = "${aws_vpc.default.id}"
   715      tags {
   716          Name        = "tf-nat-sg"
   717      }
   718  }
   719  
   720  resource "aws_security_group_rule" "source_ingress" {
   721      type        = "ingress"
   722      from_port   = 80
   723      to_port     = 80
   724      protocol    = "tcp"
   725  
   726                  source_security_group_id = "${aws_security_group.nat.id}"
   727     security_group_id = "${aws_security_group.web.id}"
   728  }
   729  
   730  resource "aws_security_group_rule" "other_ingress" {
   731      type        = "ingress"
   732      from_port   = 80
   733      to_port     = 80
   734      protocol    = "tcp"
   735      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   736  
   737     security_group_id = "${aws_security_group.web.id}"
   738  }
   739  `
   740  
   741  var testAccAWSSecurityGroupRuleRace = func() string {
   742  	var b bytes.Buffer
   743  	iterations := 50
   744  	b.WriteString(fmt.Sprintf(`
   745  		resource "aws_vpc" "default" {
   746  			cidr_block = "10.0.0.0/16"
   747  			tags { Name = "tf-sg-rule-race" }
   748  		}
   749  
   750  		resource "aws_security_group" "race" {
   751  			name   = "tf-sg-rule-race-group-%d"
   752  			vpc_id = "${aws_vpc.default.id}"
   753  		}
   754  	`, acctest.RandInt()))
   755  	for i := 1; i < iterations; i++ {
   756  		b.WriteString(fmt.Sprintf(`
   757  			resource "aws_security_group_rule" "ingress%d" {
   758  				security_group_id = "${aws_security_group.race.id}"
   759  				type              = "ingress"
   760  				from_port         = %d
   761  				to_port           = %d
   762  				protocol          = "tcp"
   763  				cidr_blocks       = ["10.0.0.%d/32"]
   764  			}
   765  
   766  			resource "aws_security_group_rule" "egress%d" {
   767  				security_group_id = "${aws_security_group.race.id}"
   768  				type              = "egress"
   769  				from_port         = %d
   770  				to_port           = %d
   771  				protocol          = "tcp"
   772  				cidr_blocks       = ["10.0.0.%d/32"]
   773  			}
   774  		`, i, i, i, i, i, i, i, i))
   775  	}
   776  	return b.String()
   777  }()