github.com/subuk/terraform@v0.6.14-0.20160317140351-de1567c2e732/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_Issue5310(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: testAccAWSSecurityGroupRuleIssue5310,
   356  				Check: resource.ComposeTestCheckFunc(
   357  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group),
   358  				),
   359  			},
   360  		},
   361  	})
   362  }
   363  
   364  func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
   365  	var group ec2.SecurityGroup
   366  
   367  	resource.Test(t, resource.TestCase{
   368  		PreCheck:     func() { testAccPreCheck(t) },
   369  		Providers:    testAccProviders,
   370  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   371  		Steps: []resource.TestStep{
   372  			resource.TestStep{
   373  				Config: testAccAWSSecurityGroupRuleRace,
   374  				Check: resource.ComposeTestCheckFunc(
   375  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group),
   376  				),
   377  			},
   378  		},
   379  	})
   380  }
   381  
   382  func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
   383  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   384  
   385  	for _, rs := range s.RootModule().Resources {
   386  		if rs.Type != "aws_security_group" {
   387  			continue
   388  		}
   389  
   390  		// Retrieve our group
   391  		req := &ec2.DescribeSecurityGroupsInput{
   392  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   393  		}
   394  		resp, err := conn.DescribeSecurityGroups(req)
   395  		if err == nil {
   396  			if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   397  				return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
   398  			}
   399  
   400  			return nil
   401  		}
   402  
   403  		ec2err, ok := err.(awserr.Error)
   404  		if !ok {
   405  			return err
   406  		}
   407  		// Confirm error code is what we want
   408  		if ec2err.Code() != "InvalidGroup.NotFound" {
   409  			return err
   410  		}
   411  	}
   412  
   413  	return nil
   414  }
   415  
   416  func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
   417  	return func(s *terraform.State) error {
   418  		rs, ok := s.RootModule().Resources[n]
   419  		if !ok {
   420  			return fmt.Errorf("Not found: %s", n)
   421  		}
   422  
   423  		if rs.Primary.ID == "" {
   424  			return fmt.Errorf("No Security Group is set")
   425  		}
   426  
   427  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   428  		req := &ec2.DescribeSecurityGroupsInput{
   429  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   430  		}
   431  		resp, err := conn.DescribeSecurityGroups(req)
   432  		if err != nil {
   433  			return err
   434  		}
   435  
   436  		if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   437  			*group = *resp.SecurityGroups[0]
   438  			return nil
   439  		}
   440  
   441  		return fmt.Errorf("Security Group not found")
   442  	}
   443  }
   444  
   445  func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
   446  	return func(s *terraform.State) error {
   447  		rs, ok := s.RootModule().Resources[n]
   448  		if !ok {
   449  			return fmt.Errorf("Security Group Rule Not found: %s", n)
   450  		}
   451  
   452  		if rs.Primary.ID == "" {
   453  			return fmt.Errorf("No Security Group Rule is set")
   454  		}
   455  
   456  		if p == nil {
   457  			p = &ec2.IpPermission{
   458  				FromPort:   aws.Int64(80),
   459  				ToPort:     aws.Int64(8000),
   460  				IpProtocol: aws.String("tcp"),
   461  				IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("10.0.0.0/8")}},
   462  			}
   463  		}
   464  
   465  		var matchingRule *ec2.IpPermission
   466  		var rules []*ec2.IpPermission
   467  		if ruleType == "ingress" {
   468  			rules = group.IpPermissions
   469  		} else {
   470  			rules = group.IpPermissionsEgress
   471  		}
   472  
   473  		if len(rules) == 0 {
   474  			return fmt.Errorf("No IPPerms")
   475  		}
   476  
   477  		for _, r := range rules {
   478  			if r.ToPort != nil && *p.ToPort != *r.ToPort {
   479  				continue
   480  			}
   481  
   482  			if r.FromPort != nil && *p.FromPort != *r.FromPort {
   483  				continue
   484  			}
   485  
   486  			if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
   487  				continue
   488  			}
   489  
   490  			remaining := len(p.IpRanges)
   491  			for _, ip := range p.IpRanges {
   492  				for _, rip := range r.IpRanges {
   493  					if *ip.CidrIp == *rip.CidrIp {
   494  						remaining--
   495  					}
   496  				}
   497  			}
   498  
   499  			if remaining > 0 {
   500  				continue
   501  			}
   502  
   503  			remaining = len(p.UserIdGroupPairs)
   504  			for _, ip := range p.UserIdGroupPairs {
   505  				for _, rip := range r.UserIdGroupPairs {
   506  					if *ip.GroupId == *rip.GroupId {
   507  						remaining--
   508  					}
   509  				}
   510  			}
   511  
   512  			if remaining > 0 {
   513  				continue
   514  			}
   515  			matchingRule = r
   516  		}
   517  
   518  		if matchingRule != nil {
   519  			log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
   520  			return nil
   521  		}
   522  
   523  		return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
   524  	}
   525  }
   526  
   527  const testAccAWSSecurityGroupRuleIngressConfig = `
   528  resource "aws_security_group" "web" {
   529    name = "terraform_acceptance_test_example"
   530    description = "Used in the terraform acceptance tests"
   531  
   532          tags {
   533                  Name = "tf-acc-test"
   534          }
   535  }
   536  
   537  resource "aws_security_group_rule" "ingress_1" {
   538    type = "ingress"
   539    protocol = "tcp"
   540    from_port = 80
   541    to_port = 8000
   542    cidr_blocks = ["10.0.0.0/8"]
   543  
   544    security_group_id = "${aws_security_group.web.id}"
   545  }
   546  `
   547  
   548  const testAccAWSSecurityGroupRuleIssue5310 = `
   549  provider "aws" {
   550          region = "us-east-1"
   551  }
   552  
   553  resource "aws_security_group" "issue_5310" {
   554      name = "terraform-test-issue_5310"
   555      description = "SG for test of issue 5310"
   556  }
   557  
   558  resource "aws_security_group_rule" "issue_5310" {
   559      type = "ingress"
   560      from_port = 0
   561      to_port = 65535
   562      protocol = "tcp"
   563      security_group_id = "${aws_security_group.issue_5310.id}"
   564      self = true
   565  }
   566  `
   567  
   568  const testAccAWSSecurityGroupRuleIngressClassicConfig = `
   569  provider "aws" {
   570          region = "us-east-1"
   571  }
   572  
   573  resource "aws_security_group" "web" {
   574    name = "terraform_acceptance_test_example"
   575    description = "Used in the terraform acceptance tests"
   576  
   577          tags {
   578                  Name = "tf-acc-test"
   579          }
   580  }
   581  
   582  resource "aws_security_group_rule" "ingress_1" {
   583    type = "ingress"
   584    protocol = "tcp"
   585    from_port = 80
   586    to_port = 8000
   587    cidr_blocks = ["10.0.0.0/8"]
   588  
   589    security_group_id = "${aws_security_group.web.id}"
   590  }
   591  `
   592  
   593  const testAccAWSSecurityGroupRuleEgressConfig = `
   594  resource "aws_security_group" "web" {
   595    name = "terraform_acceptance_test_example"
   596    description = "Used in the terraform acceptance tests"
   597  
   598          tags {
   599                  Name = "tf-acc-test"
   600          }
   601  }
   602  
   603  resource "aws_security_group_rule" "egress_1" {
   604    type = "egress"
   605    protocol = "tcp"
   606    from_port = 80
   607    to_port = 8000
   608    cidr_blocks = ["10.0.0.0/8"]
   609  
   610    security_group_id = "${aws_security_group.web.id}"
   611  }
   612  `
   613  
   614  const testAccAWSSecurityGroupRuleConfigMultiIngress = `
   615  resource "aws_security_group" "web" {
   616    name = "terraform_acceptance_test_example_2"
   617    description = "Used in the terraform acceptance tests"
   618  }
   619  
   620  resource "aws_security_group" "worker" {
   621    name = "terraform_acceptance_test_example_worker"
   622    description = "Used in the terraform acceptance tests"
   623  }
   624  
   625  
   626  resource "aws_security_group_rule" "ingress_1" {
   627    type = "ingress"
   628    protocol = "tcp"
   629    from_port = 22
   630    to_port = 22
   631    cidr_blocks = ["10.0.0.0/8"]
   632  
   633    security_group_id = "${aws_security_group.web.id}"
   634  }
   635  
   636  resource "aws_security_group_rule" "ingress_2" {
   637    type = "ingress"
   638    protocol = "tcp"
   639    from_port = 80
   640    to_port = 8000
   641          self = true
   642  
   643    security_group_id = "${aws_security_group.web.id}"
   644  }
   645  `
   646  
   647  // check for GH-1985 regression
   648  const testAccAWSSecurityGroupRuleConfigSelfReference = `
   649  provider "aws" {
   650    region = "us-west-2"
   651  }
   652  
   653  resource "aws_vpc" "main" {
   654    cidr_block = "10.0.0.0/16"
   655    tags {
   656      Name = "sg-self-test"
   657    }
   658  }
   659  
   660  resource "aws_security_group" "web" {
   661    name = "main"
   662    vpc_id = "${aws_vpc.main.id}"
   663    tags {
   664      Name = "sg-self-test"
   665    }
   666  }
   667  
   668  resource "aws_security_group_rule" "self" {
   669    type = "ingress"
   670    protocol = "-1"
   671    from_port = 0
   672    to_port = 0
   673    self = true
   674    security_group_id = "${aws_security_group.web.id}"
   675  }
   676  `
   677  
   678  const testAccAWSSecurityGroupRulePartialMatching = `
   679  resource "aws_vpc" "default" {
   680    cidr_block = "10.0.0.0/16"
   681    tags {
   682      Name = "tf-sg-rule-bug"
   683    }
   684  }
   685  
   686  resource "aws_security_group" "web" {
   687      name = "tf-other"
   688      vpc_id = "${aws_vpc.default.id}"
   689      tags {
   690          Name        = "tf-other-sg"
   691      }
   692  }
   693  
   694  resource "aws_security_group" "nat" {
   695      name = "tf-nat"
   696      vpc_id = "${aws_vpc.default.id}"
   697      tags {
   698          Name        = "tf-nat-sg"
   699      }
   700  }
   701  
   702  resource "aws_security_group_rule" "ingress" {
   703      type        = "ingress"
   704      from_port   = 80
   705      to_port     = 80
   706      protocol    = "tcp"
   707      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   708  
   709     security_group_id = "${aws_security_group.web.id}"
   710  }
   711  
   712  resource "aws_security_group_rule" "other" {
   713      type        = "ingress"
   714      from_port   = 80
   715      to_port     = 80
   716      protocol    = "tcp"
   717      cidr_blocks = ["10.0.5.0/24"]
   718  
   719     security_group_id = "${aws_security_group.web.id}"
   720  }
   721  
   722  // same a above, but different group, to guard against bad hashing
   723  resource "aws_security_group_rule" "nat_ingress" {
   724      type        = "ingress"
   725      from_port   = 80
   726      to_port     = 80
   727      protocol    = "tcp"
   728      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   729  
   730     security_group_id = "${aws_security_group.nat.id}"
   731  }
   732  `
   733  
   734  const testAccAWSSecurityGroupRulePartialMatching_Source = `
   735  resource "aws_vpc" "default" {
   736    cidr_block = "10.0.0.0/16"
   737    tags {
   738      Name = "tf-sg-rule-bug"
   739    }
   740  }
   741  
   742  resource "aws_security_group" "web" {
   743      name = "tf-other"
   744      vpc_id = "${aws_vpc.default.id}"
   745      tags {
   746          Name        = "tf-other-sg"
   747      }
   748  }
   749  
   750  resource "aws_security_group" "nat" {
   751      name = "tf-nat"
   752      vpc_id = "${aws_vpc.default.id}"
   753      tags {
   754          Name        = "tf-nat-sg"
   755      }
   756  }
   757  
   758  resource "aws_security_group_rule" "source_ingress" {
   759      type        = "ingress"
   760      from_port   = 80
   761      to_port     = 80
   762      protocol    = "tcp"
   763  
   764                  source_security_group_id = "${aws_security_group.nat.id}"
   765     security_group_id = "${aws_security_group.web.id}"
   766  }
   767  
   768  resource "aws_security_group_rule" "other_ingress" {
   769      type        = "ingress"
   770      from_port   = 80
   771      to_port     = 80
   772      protocol    = "tcp"
   773      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   774  
   775     security_group_id = "${aws_security_group.web.id}"
   776  }
   777  `
   778  
   779  var testAccAWSSecurityGroupRuleRace = func() string {
   780  	var b bytes.Buffer
   781  	iterations := 50
   782  	b.WriteString(fmt.Sprintf(`
   783  		resource "aws_vpc" "default" {
   784  			cidr_block = "10.0.0.0/16"
   785  			tags { Name = "tf-sg-rule-race" }
   786  		}
   787  
   788  		resource "aws_security_group" "race" {
   789  			name   = "tf-sg-rule-race-group-%d"
   790  			vpc_id = "${aws_vpc.default.id}"
   791  		}
   792  	`, acctest.RandInt()))
   793  	for i := 1; i < iterations; i++ {
   794  		b.WriteString(fmt.Sprintf(`
   795  			resource "aws_security_group_rule" "ingress%d" {
   796  				security_group_id = "${aws_security_group.race.id}"
   797  				type              = "ingress"
   798  				from_port         = %d
   799  				to_port           = %d
   800  				protocol          = "tcp"
   801  				cidr_blocks       = ["10.0.0.%d/32"]
   802  			}
   803  
   804  			resource "aws_security_group_rule" "egress%d" {
   805  				security_group_id = "${aws_security_group.race.id}"
   806  				type              = "egress"
   807  				from_port         = %d
   808  				to_port           = %d
   809  				protocol          = "tcp"
   810  				cidr_blocks       = ["10.0.0.%d/32"]
   811  			}
   812  		`, i, i, i, i, i, i, i, i))
   813  	}
   814  	return b.String()
   815  }()