github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/builtin/providers/aws/resource_aws_security_group_rule_test.go (about)

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