github.com/gabrielperezs/terraform@v0.7.0-rc2.0.20160715084931-f7da2612946f/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_Protocol(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: testAccAWSSecurityGroupRuleIngress_protocolConfig,
   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_Ingress_Classic(t *testing.T) {
   185  	var group ec2.SecurityGroup
   186  
   187  	testRuleCount := func(*terraform.State) error {
   188  		if len(group.IpPermissions) != 1 {
   189  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   190  				1, len(group.IpPermissions))
   191  		}
   192  
   193  		rule := group.IpPermissions[0]
   194  		if *rule.FromPort != int64(80) {
   195  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   196  				80, int(*rule.FromPort))
   197  		}
   198  
   199  		return nil
   200  	}
   201  
   202  	resource.Test(t, resource.TestCase{
   203  		PreCheck:     func() { testAccPreCheck(t) },
   204  		Providers:    testAccProviders,
   205  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   206  		Steps: []resource.TestStep{
   207  			resource.TestStep{
   208  				Config: testAccAWSSecurityGroupRuleIngressClassicConfig,
   209  				Check: resource.ComposeTestCheckFunc(
   210  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   211  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   212  					resource.TestCheckResourceAttr(
   213  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   214  					testRuleCount,
   215  				),
   216  			},
   217  		},
   218  	})
   219  }
   220  
   221  func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) {
   222  	var group ec2.SecurityGroup
   223  
   224  	testMultiRuleCount := func(*terraform.State) error {
   225  		if len(group.IpPermissions) != 2 {
   226  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   227  				2, len(group.IpPermissions))
   228  		}
   229  
   230  		var rule *ec2.IpPermission
   231  		for _, r := range group.IpPermissions {
   232  			if *r.FromPort == int64(80) {
   233  				rule = r
   234  			}
   235  		}
   236  
   237  		if *rule.ToPort != int64(8000) {
   238  			return fmt.Errorf("Wrong Security Group port 2 setting, expected %d, got %d",
   239  				8000, int(*rule.ToPort))
   240  		}
   241  
   242  		return nil
   243  	}
   244  
   245  	resource.Test(t, resource.TestCase{
   246  		PreCheck:     func() { testAccPreCheck(t) },
   247  		Providers:    testAccProviders,
   248  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   249  		Steps: []resource.TestStep{
   250  			resource.TestStep{
   251  				Config: testAccAWSSecurityGroupRuleConfigMultiIngress,
   252  				Check: resource.ComposeTestCheckFunc(
   253  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   254  					testMultiRuleCount,
   255  				),
   256  			},
   257  		},
   258  	})
   259  }
   260  
   261  func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
   262  	var group ec2.SecurityGroup
   263  
   264  	resource.Test(t, resource.TestCase{
   265  		PreCheck:     func() { testAccPreCheck(t) },
   266  		Providers:    testAccProviders,
   267  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   268  		Steps: []resource.TestStep{
   269  			resource.TestStep{
   270  				Config: testAccAWSSecurityGroupRuleEgressConfig,
   271  				Check: resource.ComposeTestCheckFunc(
   272  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   273  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"),
   274  				),
   275  			},
   276  		},
   277  	})
   278  }
   279  
   280  func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) {
   281  	var group ec2.SecurityGroup
   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: testAccAWSSecurityGroupRuleConfigSelfReference,
   290  				Check: resource.ComposeTestCheckFunc(
   291  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   292  				),
   293  			},
   294  		},
   295  	})
   296  }
   297  
   298  // testing partial match implementation
   299  func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
   300  	var group ec2.SecurityGroup
   301  
   302  	p := ec2.IpPermission{
   303  		FromPort:   aws.Int64(80),
   304  		ToPort:     aws.Int64(80),
   305  		IpProtocol: aws.String("tcp"),
   306  		IpRanges: []*ec2.IpRange{
   307  			&ec2.IpRange{CidrIp: aws.String("10.0.2.0/24")},
   308  			&ec2.IpRange{CidrIp: aws.String("10.0.3.0/24")},
   309  			&ec2.IpRange{CidrIp: aws.String("10.0.4.0/24")},
   310  		},
   311  	}
   312  
   313  	o := ec2.IpPermission{
   314  		FromPort:   aws.Int64(80),
   315  		ToPort:     aws.Int64(80),
   316  		IpProtocol: aws.String("tcp"),
   317  		IpRanges: []*ec2.IpRange{
   318  			&ec2.IpRange{CidrIp: aws.String("10.0.5.0/24")},
   319  		},
   320  	}
   321  
   322  	resource.Test(t, resource.TestCase{
   323  		PreCheck:     func() { testAccPreCheck(t) },
   324  		Providers:    testAccProviders,
   325  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   326  		Steps: []resource.TestStep{
   327  			resource.TestStep{
   328  				Config: testAccAWSSecurityGroupRulePartialMatching,
   329  				Check: resource.ComposeTestCheckFunc(
   330  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   331  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"),
   332  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.other", &group, &o, "ingress"),
   333  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"),
   334  				),
   335  			},
   336  		},
   337  	})
   338  }
   339  
   340  func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
   341  	var group ec2.SecurityGroup
   342  	var nat ec2.SecurityGroup
   343  	var p ec2.IpPermission
   344  
   345  	// This function creates the expected IPPermission with the group id from an
   346  	// external security group, needed because Security Group IDs are generated on
   347  	// AWS side and can't be known ahead of time.
   348  	setupSG := func(*terraform.State) error {
   349  		if nat.GroupId == nil {
   350  			return fmt.Errorf("Error: nat group has nil GroupID")
   351  		}
   352  
   353  		p = ec2.IpPermission{
   354  			FromPort:   aws.Int64(80),
   355  			ToPort:     aws.Int64(80),
   356  			IpProtocol: aws.String("tcp"),
   357  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   358  				&ec2.UserIdGroupPair{GroupId: nat.GroupId},
   359  			},
   360  		}
   361  
   362  		return nil
   363  	}
   364  
   365  	resource.Test(t, resource.TestCase{
   366  		PreCheck:     func() { testAccPreCheck(t) },
   367  		Providers:    testAccProviders,
   368  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   369  		Steps: []resource.TestStep{
   370  			resource.TestStep{
   371  				Config: testAccAWSSecurityGroupRulePartialMatching_Source,
   372  				Check: resource.ComposeTestCheckFunc(
   373  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   374  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat),
   375  					setupSG,
   376  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"),
   377  				),
   378  			},
   379  		},
   380  	})
   381  }
   382  
   383  func TestAccAWSSecurityGroupRule_Issue5310(t *testing.T) {
   384  	var group ec2.SecurityGroup
   385  
   386  	resource.Test(t, resource.TestCase{
   387  		PreCheck:     func() { testAccPreCheck(t) },
   388  		Providers:    testAccProviders,
   389  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   390  		Steps: []resource.TestStep{
   391  			resource.TestStep{
   392  				Config: testAccAWSSecurityGroupRuleIssue5310,
   393  				Check: resource.ComposeTestCheckFunc(
   394  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group),
   395  				),
   396  			},
   397  		},
   398  	})
   399  }
   400  
   401  func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
   402  	var group ec2.SecurityGroup
   403  
   404  	resource.Test(t, resource.TestCase{
   405  		PreCheck:     func() { testAccPreCheck(t) },
   406  		Providers:    testAccProviders,
   407  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   408  		Steps: []resource.TestStep{
   409  			resource.TestStep{
   410  				Config: testAccAWSSecurityGroupRuleRace,
   411  				Check: resource.ComposeTestCheckFunc(
   412  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group),
   413  				),
   414  			},
   415  		},
   416  	})
   417  }
   418  
   419  func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) {
   420  	var group ec2.SecurityGroup
   421  	var endpoint ec2.VpcEndpoint
   422  	var p ec2.IpPermission
   423  
   424  	// This function creates the expected IPPermission with the prefix list ID from
   425  	// the VPC Endpoint created in the test
   426  	setupSG := func(*terraform.State) error {
   427  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   428  		prefixListInput := &ec2.DescribePrefixListsInput{
   429  			Filters: []*ec2.Filter{
   430  				{Name: aws.String("prefix-list-name"), Values: []*string{endpoint.ServiceName}},
   431  			},
   432  		}
   433  
   434  		log.Printf("[DEBUG] Reading VPC Endpoint prefix list: %s", prefixListInput)
   435  		prefixListsOutput, err := conn.DescribePrefixLists(prefixListInput)
   436  
   437  		if err != nil {
   438  			_, ok := err.(awserr.Error)
   439  			if !ok {
   440  				return fmt.Errorf("Error reading VPC Endpoint prefix list: %s", err.Error())
   441  			}
   442  		}
   443  
   444  		if len(prefixListsOutput.PrefixLists) != 1 {
   445  			return fmt.Errorf("There are multiple prefix lists associated with the service name '%s'. Unexpected", prefixListsOutput)
   446  		}
   447  
   448  		p = ec2.IpPermission{
   449  			IpProtocol: aws.String("-1"),
   450  			PrefixListIds: []*ec2.PrefixListId{
   451  				&ec2.PrefixListId{PrefixListId: prefixListsOutput.PrefixLists[0].PrefixListId},
   452  			},
   453  		}
   454  
   455  		return nil
   456  	}
   457  
   458  	resource.Test(t, resource.TestCase{
   459  		PreCheck:     func() { testAccPreCheck(t) },
   460  		Providers:    testAccProviders,
   461  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   462  		Steps: []resource.TestStep{
   463  			resource.TestStep{
   464  				Config: testAccAWSSecurityGroupRulePrefixListEgressConfig,
   465  				Check: resource.ComposeTestCheckFunc(
   466  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.egress", &group),
   467  					// lookup info on the VPC Endpoint created, to populate the expected
   468  					// IP Perm
   469  					testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3-us-west-2", &endpoint),
   470  					setupSG,
   471  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"),
   472  				),
   473  			},
   474  		},
   475  	})
   476  }
   477  
   478  func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
   479  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   480  
   481  	for _, rs := range s.RootModule().Resources {
   482  		if rs.Type != "aws_security_group" {
   483  			continue
   484  		}
   485  
   486  		// Retrieve our group
   487  		req := &ec2.DescribeSecurityGroupsInput{
   488  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   489  		}
   490  		resp, err := conn.DescribeSecurityGroups(req)
   491  		if err == nil {
   492  			if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   493  				return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
   494  			}
   495  
   496  			return nil
   497  		}
   498  
   499  		ec2err, ok := err.(awserr.Error)
   500  		if !ok {
   501  			return err
   502  		}
   503  		// Confirm error code is what we want
   504  		if ec2err.Code() != "InvalidGroup.NotFound" {
   505  			return err
   506  		}
   507  	}
   508  
   509  	return nil
   510  }
   511  
   512  func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
   513  	return func(s *terraform.State) error {
   514  		rs, ok := s.RootModule().Resources[n]
   515  		if !ok {
   516  			return fmt.Errorf("Not found: %s", n)
   517  		}
   518  
   519  		if rs.Primary.ID == "" {
   520  			return fmt.Errorf("No Security Group is set")
   521  		}
   522  
   523  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   524  		req := &ec2.DescribeSecurityGroupsInput{
   525  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   526  		}
   527  		resp, err := conn.DescribeSecurityGroups(req)
   528  		if err != nil {
   529  			return err
   530  		}
   531  
   532  		if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   533  			*group = *resp.SecurityGroups[0]
   534  			return nil
   535  		}
   536  
   537  		return fmt.Errorf("Security Group not found")
   538  	}
   539  }
   540  
   541  func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
   542  	return func(s *terraform.State) error {
   543  		rs, ok := s.RootModule().Resources[n]
   544  		if !ok {
   545  			return fmt.Errorf("Security Group Rule Not found: %s", n)
   546  		}
   547  
   548  		if rs.Primary.ID == "" {
   549  			return fmt.Errorf("No Security Group Rule is set")
   550  		}
   551  
   552  		if p == nil {
   553  			p = &ec2.IpPermission{
   554  				FromPort:   aws.Int64(80),
   555  				ToPort:     aws.Int64(8000),
   556  				IpProtocol: aws.String("tcp"),
   557  				IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("10.0.0.0/8")}},
   558  			}
   559  		}
   560  
   561  		var matchingRule *ec2.IpPermission
   562  		var rules []*ec2.IpPermission
   563  		if ruleType == "ingress" {
   564  			rules = group.IpPermissions
   565  		} else {
   566  			rules = group.IpPermissionsEgress
   567  		}
   568  
   569  		if len(rules) == 0 {
   570  			return fmt.Errorf("No IPPerms")
   571  		}
   572  
   573  		for _, r := range rules {
   574  			if r.ToPort != nil && *p.ToPort != *r.ToPort {
   575  				continue
   576  			}
   577  
   578  			if r.FromPort != nil && *p.FromPort != *r.FromPort {
   579  				continue
   580  			}
   581  
   582  			if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
   583  				continue
   584  			}
   585  
   586  			remaining := len(p.IpRanges)
   587  			for _, ip := range p.IpRanges {
   588  				for _, rip := range r.IpRanges {
   589  					if *ip.CidrIp == *rip.CidrIp {
   590  						remaining--
   591  					}
   592  				}
   593  			}
   594  
   595  			if remaining > 0 {
   596  				continue
   597  			}
   598  
   599  			remaining = len(p.UserIdGroupPairs)
   600  			for _, ip := range p.UserIdGroupPairs {
   601  				for _, rip := range r.UserIdGroupPairs {
   602  					if *ip.GroupId == *rip.GroupId {
   603  						remaining--
   604  					}
   605  				}
   606  			}
   607  
   608  			if remaining > 0 {
   609  				continue
   610  			}
   611  
   612  			remaining = len(p.PrefixListIds)
   613  			for _, pip := range p.PrefixListIds {
   614  				for _, rpip := range r.PrefixListIds {
   615  					if *pip.PrefixListId == *rpip.PrefixListId {
   616  						remaining--
   617  					}
   618  				}
   619  			}
   620  
   621  			if remaining > 0 {
   622  				continue
   623  			}
   624  
   625  			matchingRule = r
   626  		}
   627  
   628  		if matchingRule != nil {
   629  			log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
   630  			return nil
   631  		}
   632  
   633  		return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
   634  	}
   635  }
   636  
   637  const testAccAWSSecurityGroupRuleIngressConfig = `
   638  resource "aws_security_group" "web" {
   639    name = "terraform_acceptance_test_example"
   640    description = "Used in the terraform acceptance tests"
   641  
   642          tags {
   643                  Name = "tf-acc-test"
   644          }
   645  }
   646  
   647  resource "aws_security_group_rule" "ingress_1" {
   648    type = "ingress"
   649    protocol = "tcp"
   650    from_port = 80
   651    to_port = 8000
   652    cidr_blocks = ["10.0.0.0/8"]
   653  
   654    security_group_id = "${aws_security_group.web.id}"
   655  }
   656  `
   657  
   658  const testAccAWSSecurityGroupRuleIngress_protocolConfig = `
   659  resource "aws_vpc" "tftest" {
   660    cidr_block = "10.0.0.0/16"
   661  
   662    tags {
   663      Name = "tf-testing"
   664    }
   665  }
   666  
   667  resource "aws_security_group" "web" {
   668    vpc_id = "${aws_vpc.tftest.id}"
   669  
   670    tags {
   671      Name = "tf-acc-test"
   672    }
   673  }
   674  
   675  resource "aws_security_group_rule" "ingress_1" {
   676    type        = "ingress"
   677    protocol    = "6"
   678    from_port   = 80
   679    to_port     = 8000
   680    cidr_blocks = ["10.0.0.0/8"]
   681  
   682    security_group_id = "${aws_security_group.web.id}"
   683  }
   684  
   685  `
   686  
   687  const testAccAWSSecurityGroupRuleIssue5310 = `
   688  provider "aws" {
   689          region = "us-east-1"
   690  }
   691  
   692  resource "aws_security_group" "issue_5310" {
   693      name = "terraform-test-issue_5310"
   694      description = "SG for test of issue 5310"
   695  }
   696  
   697  resource "aws_security_group_rule" "issue_5310" {
   698      type = "ingress"
   699      from_port = 0
   700      to_port = 65535
   701      protocol = "tcp"
   702      security_group_id = "${aws_security_group.issue_5310.id}"
   703      self = true
   704  }
   705  `
   706  
   707  const testAccAWSSecurityGroupRuleIngressClassicConfig = `
   708  provider "aws" {
   709          region = "us-east-1"
   710  }
   711  
   712  resource "aws_security_group" "web" {
   713    name = "terraform_acceptance_test_example"
   714    description = "Used in the terraform acceptance tests"
   715  
   716          tags {
   717                  Name = "tf-acc-test"
   718          }
   719  }
   720  
   721  resource "aws_security_group_rule" "ingress_1" {
   722    type = "ingress"
   723    protocol = "tcp"
   724    from_port = 80
   725    to_port = 8000
   726    cidr_blocks = ["10.0.0.0/8"]
   727  
   728    security_group_id = "${aws_security_group.web.id}"
   729  }
   730  `
   731  
   732  const testAccAWSSecurityGroupRuleEgressConfig = `
   733  resource "aws_security_group" "web" {
   734    name = "terraform_acceptance_test_example"
   735    description = "Used in the terraform acceptance tests"
   736  
   737          tags {
   738                  Name = "tf-acc-test"
   739          }
   740  }
   741  
   742  resource "aws_security_group_rule" "egress_1" {
   743    type = "egress"
   744    protocol = "tcp"
   745    from_port = 80
   746    to_port = 8000
   747    cidr_blocks = ["10.0.0.0/8"]
   748  
   749    security_group_id = "${aws_security_group.web.id}"
   750  }
   751  `
   752  
   753  const testAccAWSSecurityGroupRuleConfigMultiIngress = `
   754  resource "aws_security_group" "web" {
   755    name = "terraform_acceptance_test_example_2"
   756    description = "Used in the terraform acceptance tests"
   757  }
   758  
   759  resource "aws_security_group" "worker" {
   760    name = "terraform_acceptance_test_example_worker"
   761    description = "Used in the terraform acceptance tests"
   762  }
   763  
   764  
   765  resource "aws_security_group_rule" "ingress_1" {
   766    type = "ingress"
   767    protocol = "tcp"
   768    from_port = 22
   769    to_port = 22
   770    cidr_blocks = ["10.0.0.0/8"]
   771  
   772    security_group_id = "${aws_security_group.web.id}"
   773  }
   774  
   775  resource "aws_security_group_rule" "ingress_2" {
   776    type = "ingress"
   777    protocol = "tcp"
   778    from_port = 80
   779    to_port = 8000
   780          self = true
   781  
   782    security_group_id = "${aws_security_group.web.id}"
   783  }
   784  `
   785  
   786  // check for GH-1985 regression
   787  const testAccAWSSecurityGroupRuleConfigSelfReference = `
   788  provider "aws" {
   789    region = "us-west-2"
   790  }
   791  
   792  resource "aws_vpc" "main" {
   793    cidr_block = "10.0.0.0/16"
   794    tags {
   795      Name = "sg-self-test"
   796    }
   797  }
   798  
   799  resource "aws_security_group" "web" {
   800    name = "main"
   801    vpc_id = "${aws_vpc.main.id}"
   802    tags {
   803      Name = "sg-self-test"
   804    }
   805  }
   806  
   807  resource "aws_security_group_rule" "self" {
   808    type = "ingress"
   809    protocol = "-1"
   810    from_port = 0
   811    to_port = 0
   812    self = true
   813    security_group_id = "${aws_security_group.web.id}"
   814  }
   815  `
   816  
   817  const testAccAWSSecurityGroupRulePartialMatching = `
   818  resource "aws_vpc" "default" {
   819    cidr_block = "10.0.0.0/16"
   820    tags {
   821      Name = "tf-sg-rule-bug"
   822    }
   823  }
   824  
   825  resource "aws_security_group" "web" {
   826      name = "tf-other"
   827      vpc_id = "${aws_vpc.default.id}"
   828      tags {
   829          Name        = "tf-other-sg"
   830      }
   831  }
   832  
   833  resource "aws_security_group" "nat" {
   834      name = "tf-nat"
   835      vpc_id = "${aws_vpc.default.id}"
   836      tags {
   837          Name        = "tf-nat-sg"
   838      }
   839  }
   840  
   841  resource "aws_security_group_rule" "ingress" {
   842      type        = "ingress"
   843      from_port   = 80
   844      to_port     = 80
   845      protocol    = "tcp"
   846      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   847  
   848     security_group_id = "${aws_security_group.web.id}"
   849  }
   850  
   851  resource "aws_security_group_rule" "other" {
   852      type        = "ingress"
   853      from_port   = 80
   854      to_port     = 80
   855      protocol    = "tcp"
   856      cidr_blocks = ["10.0.5.0/24"]
   857  
   858     security_group_id = "${aws_security_group.web.id}"
   859  }
   860  
   861  // same a above, but different group, to guard against bad hashing
   862  resource "aws_security_group_rule" "nat_ingress" {
   863      type        = "ingress"
   864      from_port   = 80
   865      to_port     = 80
   866      protocol    = "tcp"
   867      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   868  
   869     security_group_id = "${aws_security_group.nat.id}"
   870  }
   871  `
   872  
   873  const testAccAWSSecurityGroupRulePartialMatching_Source = `
   874  resource "aws_vpc" "default" {
   875    cidr_block = "10.0.0.0/16"
   876    tags {
   877      Name = "tf-sg-rule-bug"
   878    }
   879  }
   880  
   881  resource "aws_security_group" "web" {
   882      name = "tf-other"
   883      vpc_id = "${aws_vpc.default.id}"
   884      tags {
   885          Name        = "tf-other-sg"
   886      }
   887  }
   888  
   889  resource "aws_security_group" "nat" {
   890      name = "tf-nat"
   891      vpc_id = "${aws_vpc.default.id}"
   892      tags {
   893          Name        = "tf-nat-sg"
   894      }
   895  }
   896  
   897  resource "aws_security_group_rule" "source_ingress" {
   898      type        = "ingress"
   899      from_port   = 80
   900      to_port     = 80
   901      protocol    = "tcp"
   902  
   903                  source_security_group_id = "${aws_security_group.nat.id}"
   904     security_group_id = "${aws_security_group.web.id}"
   905  }
   906  
   907  resource "aws_security_group_rule" "other_ingress" {
   908      type        = "ingress"
   909      from_port   = 80
   910      to_port     = 80
   911      protocol    = "tcp"
   912      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   913  
   914     security_group_id = "${aws_security_group.web.id}"
   915  }
   916  `
   917  
   918  var testAccAWSSecurityGroupRuleRace = func() string {
   919  	var b bytes.Buffer
   920  	iterations := 50
   921  	b.WriteString(fmt.Sprintf(`
   922  		resource "aws_vpc" "default" {
   923  			cidr_block = "10.0.0.0/16"
   924  			tags { Name = "tf-sg-rule-race" }
   925  		}
   926  
   927  		resource "aws_security_group" "race" {
   928  			name   = "tf-sg-rule-race-group-%d"
   929  			vpc_id = "${aws_vpc.default.id}"
   930  		}
   931  	`, acctest.RandInt()))
   932  	for i := 1; i < iterations; i++ {
   933  		b.WriteString(fmt.Sprintf(`
   934  			resource "aws_security_group_rule" "ingress%d" {
   935  				security_group_id = "${aws_security_group.race.id}"
   936  				type              = "ingress"
   937  				from_port         = %d
   938  				to_port           = %d
   939  				protocol          = "tcp"
   940  				cidr_blocks       = ["10.0.0.%d/32"]
   941  			}
   942  
   943  			resource "aws_security_group_rule" "egress%d" {
   944  				security_group_id = "${aws_security_group.race.id}"
   945  				type              = "egress"
   946  				from_port         = %d
   947  				to_port           = %d
   948  				protocol          = "tcp"
   949  				cidr_blocks       = ["10.0.0.%d/32"]
   950  			}
   951  		`, i, i, i, i, i, i, i, i))
   952  	}
   953  	return b.String()
   954  }()
   955  
   956  const testAccAWSSecurityGroupRulePrefixListEgressConfig = `
   957  
   958  resource "aws_vpc" "tf_sg_prefix_list_egress_test" {
   959      cidr_block = "10.0.0.0/16"
   960      tags {
   961              Name = "tf_sg_prefix_list_egress_test"
   962      }
   963  }
   964  
   965  resource "aws_route_table" "default" {
   966      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
   967  }
   968  
   969  resource "aws_vpc_endpoint" "s3-us-west-2" {
   970    	vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
   971    	service_name = "com.amazonaws.us-west-2.s3"
   972    	route_table_ids = ["${aws_route_table.default.id}"]
   973    	policy = <<POLICY
   974  {
   975  	"Version": "2012-10-17",
   976  	"Statement": [
   977  		{
   978  			"Sid":"AllowAll",
   979  			"Effect":"Allow",
   980  			"Principal":"*",
   981  			"Action":"*",
   982  			"Resource":"*"
   983  		}
   984  	]
   985  }
   986  POLICY
   987  }
   988  
   989  resource "aws_security_group" "egress" {
   990      name = "terraform_acceptance_test_prefix_list_egress"
   991      description = "Used in the terraform acceptance tests"
   992      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
   993  }
   994  
   995  resource "aws_security_group_rule" "egress_1" {
   996    type = "egress"
   997    protocol = "-1"
   998    from_port = 0
   999    to_port = 0
  1000    prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"]
  1001  	security_group_id = "${aws_security_group.egress.id}"
  1002  }
  1003  `