github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/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_SelfSource(t *testing.T) {
   420  	var group ec2.SecurityGroup
   421  
   422  	resource.Test(t, resource.TestCase{
   423  		PreCheck:     func() { testAccPreCheck(t) },
   424  		Providers:    testAccProviders,
   425  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   426  		Steps: []resource.TestStep{
   427  			resource.TestStep{
   428  				Config: testAccAWSSecurityGroupRuleSelfInSource,
   429  				Check: resource.ComposeTestCheckFunc(
   430  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   431  				),
   432  			},
   433  		},
   434  	})
   435  }
   436  
   437  func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) {
   438  	var group ec2.SecurityGroup
   439  	var endpoint ec2.VpcEndpoint
   440  	var p ec2.IpPermission
   441  
   442  	// This function creates the expected IPPermission with the prefix list ID from
   443  	// the VPC Endpoint created in the test
   444  	setupSG := func(*terraform.State) error {
   445  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   446  		prefixListInput := &ec2.DescribePrefixListsInput{
   447  			Filters: []*ec2.Filter{
   448  				{Name: aws.String("prefix-list-name"), Values: []*string{endpoint.ServiceName}},
   449  			},
   450  		}
   451  
   452  		log.Printf("[DEBUG] Reading VPC Endpoint prefix list: %s", prefixListInput)
   453  		prefixListsOutput, err := conn.DescribePrefixLists(prefixListInput)
   454  
   455  		if err != nil {
   456  			_, ok := err.(awserr.Error)
   457  			if !ok {
   458  				return fmt.Errorf("Error reading VPC Endpoint prefix list: %s", err.Error())
   459  			}
   460  		}
   461  
   462  		if len(prefixListsOutput.PrefixLists) != 1 {
   463  			return fmt.Errorf("There are multiple prefix lists associated with the service name '%s'. Unexpected", prefixListsOutput)
   464  		}
   465  
   466  		p = ec2.IpPermission{
   467  			IpProtocol: aws.String("-1"),
   468  			PrefixListIds: []*ec2.PrefixListId{
   469  				&ec2.PrefixListId{PrefixListId: prefixListsOutput.PrefixLists[0].PrefixListId},
   470  			},
   471  		}
   472  
   473  		return nil
   474  	}
   475  
   476  	resource.Test(t, resource.TestCase{
   477  		PreCheck:     func() { testAccPreCheck(t) },
   478  		Providers:    testAccProviders,
   479  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   480  		Steps: []resource.TestStep{
   481  			resource.TestStep{
   482  				Config: testAccAWSSecurityGroupRulePrefixListEgressConfig,
   483  				Check: resource.ComposeTestCheckFunc(
   484  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.egress", &group),
   485  					// lookup info on the VPC Endpoint created, to populate the expected
   486  					// IP Perm
   487  					testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3-us-west-2", &endpoint),
   488  					setupSG,
   489  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"),
   490  				),
   491  			},
   492  		},
   493  	})
   494  }
   495  
   496  func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
   497  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   498  
   499  	for _, rs := range s.RootModule().Resources {
   500  		if rs.Type != "aws_security_group" {
   501  			continue
   502  		}
   503  
   504  		// Retrieve our group
   505  		req := &ec2.DescribeSecurityGroupsInput{
   506  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   507  		}
   508  		resp, err := conn.DescribeSecurityGroups(req)
   509  		if err == nil {
   510  			if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   511  				return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
   512  			}
   513  
   514  			return nil
   515  		}
   516  
   517  		ec2err, ok := err.(awserr.Error)
   518  		if !ok {
   519  			return err
   520  		}
   521  		// Confirm error code is what we want
   522  		if ec2err.Code() != "InvalidGroup.NotFound" {
   523  			return err
   524  		}
   525  	}
   526  
   527  	return nil
   528  }
   529  
   530  func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
   531  	return func(s *terraform.State) error {
   532  		rs, ok := s.RootModule().Resources[n]
   533  		if !ok {
   534  			return fmt.Errorf("Not found: %s", n)
   535  		}
   536  
   537  		if rs.Primary.ID == "" {
   538  			return fmt.Errorf("No Security Group is set")
   539  		}
   540  
   541  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   542  		req := &ec2.DescribeSecurityGroupsInput{
   543  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   544  		}
   545  		resp, err := conn.DescribeSecurityGroups(req)
   546  		if err != nil {
   547  			return err
   548  		}
   549  
   550  		if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   551  			*group = *resp.SecurityGroups[0]
   552  			return nil
   553  		}
   554  
   555  		return fmt.Errorf("Security Group not found")
   556  	}
   557  }
   558  
   559  func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
   560  	return func(s *terraform.State) error {
   561  		rs, ok := s.RootModule().Resources[n]
   562  		if !ok {
   563  			return fmt.Errorf("Security Group Rule Not found: %s", n)
   564  		}
   565  
   566  		if rs.Primary.ID == "" {
   567  			return fmt.Errorf("No Security Group Rule is set")
   568  		}
   569  
   570  		if p == nil {
   571  			p = &ec2.IpPermission{
   572  				FromPort:   aws.Int64(80),
   573  				ToPort:     aws.Int64(8000),
   574  				IpProtocol: aws.String("tcp"),
   575  				IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("10.0.0.0/8")}},
   576  			}
   577  		}
   578  
   579  		var matchingRule *ec2.IpPermission
   580  		var rules []*ec2.IpPermission
   581  		if ruleType == "ingress" {
   582  			rules = group.IpPermissions
   583  		} else {
   584  			rules = group.IpPermissionsEgress
   585  		}
   586  
   587  		if len(rules) == 0 {
   588  			return fmt.Errorf("No IPPerms")
   589  		}
   590  
   591  		for _, r := range rules {
   592  			if r.ToPort != nil && *p.ToPort != *r.ToPort {
   593  				continue
   594  			}
   595  
   596  			if r.FromPort != nil && *p.FromPort != *r.FromPort {
   597  				continue
   598  			}
   599  
   600  			if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
   601  				continue
   602  			}
   603  
   604  			remaining := len(p.IpRanges)
   605  			for _, ip := range p.IpRanges {
   606  				for _, rip := range r.IpRanges {
   607  					if *ip.CidrIp == *rip.CidrIp {
   608  						remaining--
   609  					}
   610  				}
   611  			}
   612  
   613  			if remaining > 0 {
   614  				continue
   615  			}
   616  
   617  			remaining = len(p.UserIdGroupPairs)
   618  			for _, ip := range p.UserIdGroupPairs {
   619  				for _, rip := range r.UserIdGroupPairs {
   620  					if *ip.GroupId == *rip.GroupId {
   621  						remaining--
   622  					}
   623  				}
   624  			}
   625  
   626  			if remaining > 0 {
   627  				continue
   628  			}
   629  
   630  			remaining = len(p.PrefixListIds)
   631  			for _, pip := range p.PrefixListIds {
   632  				for _, rpip := range r.PrefixListIds {
   633  					if *pip.PrefixListId == *rpip.PrefixListId {
   634  						remaining--
   635  					}
   636  				}
   637  			}
   638  
   639  			if remaining > 0 {
   640  				continue
   641  			}
   642  
   643  			matchingRule = r
   644  		}
   645  
   646  		if matchingRule != nil {
   647  			log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
   648  			return nil
   649  		}
   650  
   651  		return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
   652  	}
   653  }
   654  
   655  const testAccAWSSecurityGroupRuleIngressConfig = `
   656  resource "aws_security_group" "web" {
   657    name = "terraform_acceptance_test_example"
   658    description = "Used in the terraform acceptance tests"
   659  
   660          tags {
   661                  Name = "tf-acc-test"
   662          }
   663  }
   664  
   665  resource "aws_security_group_rule" "ingress_1" {
   666    type = "ingress"
   667    protocol = "tcp"
   668    from_port = 80
   669    to_port = 8000
   670    cidr_blocks = ["10.0.0.0/8"]
   671  
   672    security_group_id = "${aws_security_group.web.id}"
   673  }
   674  `
   675  
   676  const testAccAWSSecurityGroupRuleIngress_protocolConfig = `
   677  resource "aws_vpc" "tftest" {
   678    cidr_block = "10.0.0.0/16"
   679  
   680    tags {
   681      Name = "tf-testing"
   682    }
   683  }
   684  
   685  resource "aws_security_group" "web" {
   686    vpc_id = "${aws_vpc.tftest.id}"
   687  
   688    tags {
   689      Name = "tf-acc-test"
   690    }
   691  }
   692  
   693  resource "aws_security_group_rule" "ingress_1" {
   694    type        = "ingress"
   695    protocol    = "6"
   696    from_port   = 80
   697    to_port     = 8000
   698    cidr_blocks = ["10.0.0.0/8"]
   699  
   700    security_group_id = "${aws_security_group.web.id}"
   701  }
   702  
   703  `
   704  
   705  const testAccAWSSecurityGroupRuleIssue5310 = `
   706  provider "aws" {
   707          region = "us-east-1"
   708  }
   709  
   710  resource "aws_security_group" "issue_5310" {
   711      name = "terraform-test-issue_5310"
   712      description = "SG for test of issue 5310"
   713  }
   714  
   715  resource "aws_security_group_rule" "issue_5310" {
   716      type = "ingress"
   717      from_port = 0
   718      to_port = 65535
   719      protocol = "tcp"
   720      security_group_id = "${aws_security_group.issue_5310.id}"
   721      self = true
   722  }
   723  `
   724  
   725  const testAccAWSSecurityGroupRuleIngressClassicConfig = `
   726  provider "aws" {
   727          region = "us-east-1"
   728  }
   729  
   730  resource "aws_security_group" "web" {
   731    name = "terraform_acceptance_test_example"
   732    description = "Used in the terraform acceptance tests"
   733  
   734          tags {
   735                  Name = "tf-acc-test"
   736          }
   737  }
   738  
   739  resource "aws_security_group_rule" "ingress_1" {
   740    type = "ingress"
   741    protocol = "tcp"
   742    from_port = 80
   743    to_port = 8000
   744    cidr_blocks = ["10.0.0.0/8"]
   745  
   746    security_group_id = "${aws_security_group.web.id}"
   747  }
   748  `
   749  
   750  const testAccAWSSecurityGroupRuleEgressConfig = `
   751  resource "aws_security_group" "web" {
   752    name = "terraform_acceptance_test_example"
   753    description = "Used in the terraform acceptance tests"
   754  
   755          tags {
   756                  Name = "tf-acc-test"
   757          }
   758  }
   759  
   760  resource "aws_security_group_rule" "egress_1" {
   761    type = "egress"
   762    protocol = "tcp"
   763    from_port = 80
   764    to_port = 8000
   765    cidr_blocks = ["10.0.0.0/8"]
   766  
   767    security_group_id = "${aws_security_group.web.id}"
   768  }
   769  `
   770  
   771  const testAccAWSSecurityGroupRuleConfigMultiIngress = `
   772  resource "aws_security_group" "web" {
   773    name = "terraform_acceptance_test_example_2"
   774    description = "Used in the terraform acceptance tests"
   775  }
   776  
   777  resource "aws_security_group" "worker" {
   778    name = "terraform_acceptance_test_example_worker"
   779    description = "Used in the terraform acceptance tests"
   780  }
   781  
   782  
   783  resource "aws_security_group_rule" "ingress_1" {
   784    type = "ingress"
   785    protocol = "tcp"
   786    from_port = 22
   787    to_port = 22
   788    cidr_blocks = ["10.0.0.0/8"]
   789  
   790    security_group_id = "${aws_security_group.web.id}"
   791  }
   792  
   793  resource "aws_security_group_rule" "ingress_2" {
   794    type = "ingress"
   795    protocol = "tcp"
   796    from_port = 80
   797    to_port = 8000
   798          self = true
   799  
   800    security_group_id = "${aws_security_group.web.id}"
   801  }
   802  `
   803  
   804  // check for GH-1985 regression
   805  const testAccAWSSecurityGroupRuleConfigSelfReference = `
   806  provider "aws" {
   807    region = "us-west-2"
   808  }
   809  
   810  resource "aws_vpc" "main" {
   811    cidr_block = "10.0.0.0/16"
   812    tags {
   813      Name = "sg-self-test"
   814    }
   815  }
   816  
   817  resource "aws_security_group" "web" {
   818    name = "main"
   819    vpc_id = "${aws_vpc.main.id}"
   820    tags {
   821      Name = "sg-self-test"
   822    }
   823  }
   824  
   825  resource "aws_security_group_rule" "self" {
   826    type = "ingress"
   827    protocol = "-1"
   828    from_port = 0
   829    to_port = 0
   830    self = true
   831    security_group_id = "${aws_security_group.web.id}"
   832  }
   833  `
   834  
   835  const testAccAWSSecurityGroupRulePartialMatching = `
   836  resource "aws_vpc" "default" {
   837    cidr_block = "10.0.0.0/16"
   838    tags {
   839      Name = "tf-sg-rule-bug"
   840    }
   841  }
   842  
   843  resource "aws_security_group" "web" {
   844      name = "tf-other"
   845      vpc_id = "${aws_vpc.default.id}"
   846      tags {
   847          Name        = "tf-other-sg"
   848      }
   849  }
   850  
   851  resource "aws_security_group" "nat" {
   852      name = "tf-nat"
   853      vpc_id = "${aws_vpc.default.id}"
   854      tags {
   855          Name        = "tf-nat-sg"
   856      }
   857  }
   858  
   859  resource "aws_security_group_rule" "ingress" {
   860      type        = "ingress"
   861      from_port   = 80
   862      to_port     = 80
   863      protocol    = "tcp"
   864      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   865  
   866     security_group_id = "${aws_security_group.web.id}"
   867  }
   868  
   869  resource "aws_security_group_rule" "other" {
   870      type        = "ingress"
   871      from_port   = 80
   872      to_port     = 80
   873      protocol    = "tcp"
   874      cidr_blocks = ["10.0.5.0/24"]
   875  
   876     security_group_id = "${aws_security_group.web.id}"
   877  }
   878  
   879  // same a above, but different group, to guard against bad hashing
   880  resource "aws_security_group_rule" "nat_ingress" {
   881      type        = "ingress"
   882      from_port   = 80
   883      to_port     = 80
   884      protocol    = "tcp"
   885      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   886  
   887     security_group_id = "${aws_security_group.nat.id}"
   888  }
   889  `
   890  
   891  const testAccAWSSecurityGroupRulePartialMatching_Source = `
   892  resource "aws_vpc" "default" {
   893    cidr_block = "10.0.0.0/16"
   894    tags {
   895      Name = "tf-sg-rule-bug"
   896    }
   897  }
   898  
   899  resource "aws_security_group" "web" {
   900      name = "tf-other"
   901      vpc_id = "${aws_vpc.default.id}"
   902      tags {
   903          Name        = "tf-other-sg"
   904      }
   905  }
   906  
   907  resource "aws_security_group" "nat" {
   908      name = "tf-nat"
   909      vpc_id = "${aws_vpc.default.id}"
   910      tags {
   911          Name        = "tf-nat-sg"
   912      }
   913  }
   914  
   915  resource "aws_security_group_rule" "source_ingress" {
   916      type        = "ingress"
   917      from_port   = 80
   918      to_port     = 80
   919      protocol    = "tcp"
   920  
   921                  source_security_group_id = "${aws_security_group.nat.id}"
   922     security_group_id = "${aws_security_group.web.id}"
   923  }
   924  
   925  resource "aws_security_group_rule" "other_ingress" {
   926      type        = "ingress"
   927      from_port   = 80
   928      to_port     = 80
   929      protocol    = "tcp"
   930      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   931  
   932     security_group_id = "${aws_security_group.web.id}"
   933  }
   934  `
   935  
   936  var testAccAWSSecurityGroupRuleRace = func() string {
   937  	var b bytes.Buffer
   938  	iterations := 50
   939  	b.WriteString(fmt.Sprintf(`
   940  		resource "aws_vpc" "default" {
   941  			cidr_block = "10.0.0.0/16"
   942  			tags { Name = "tf-sg-rule-race" }
   943  		}
   944  
   945  		resource "aws_security_group" "race" {
   946  			name   = "tf-sg-rule-race-group-%d"
   947  			vpc_id = "${aws_vpc.default.id}"
   948  		}
   949  	`, acctest.RandInt()))
   950  	for i := 1; i < iterations; i++ {
   951  		b.WriteString(fmt.Sprintf(`
   952  			resource "aws_security_group_rule" "ingress%d" {
   953  				security_group_id = "${aws_security_group.race.id}"
   954  				type              = "ingress"
   955  				from_port         = %d
   956  				to_port           = %d
   957  				protocol          = "tcp"
   958  				cidr_blocks       = ["10.0.0.%d/32"]
   959  			}
   960  
   961  			resource "aws_security_group_rule" "egress%d" {
   962  				security_group_id = "${aws_security_group.race.id}"
   963  				type              = "egress"
   964  				from_port         = %d
   965  				to_port           = %d
   966  				protocol          = "tcp"
   967  				cidr_blocks       = ["10.0.0.%d/32"]
   968  			}
   969  		`, i, i, i, i, i, i, i, i))
   970  	}
   971  	return b.String()
   972  }()
   973  
   974  const testAccAWSSecurityGroupRulePrefixListEgressConfig = `
   975  
   976  resource "aws_vpc" "tf_sg_prefix_list_egress_test" {
   977      cidr_block = "10.0.0.0/16"
   978      tags {
   979              Name = "tf_sg_prefix_list_egress_test"
   980      }
   981  }
   982  
   983  resource "aws_route_table" "default" {
   984      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
   985  }
   986  
   987  resource "aws_vpc_endpoint" "s3-us-west-2" {
   988    	vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
   989    	service_name = "com.amazonaws.us-west-2.s3"
   990    	route_table_ids = ["${aws_route_table.default.id}"]
   991    	policy = <<POLICY
   992  {
   993  	"Version": "2012-10-17",
   994  	"Statement": [
   995  		{
   996  			"Sid":"AllowAll",
   997  			"Effect":"Allow",
   998  			"Principal":"*",
   999  			"Action":"*",
  1000  			"Resource":"*"
  1001  		}
  1002  	]
  1003  }
  1004  POLICY
  1005  }
  1006  
  1007  resource "aws_security_group" "egress" {
  1008      name = "terraform_acceptance_test_prefix_list_egress"
  1009      description = "Used in the terraform acceptance tests"
  1010      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
  1011  }
  1012  
  1013  resource "aws_security_group_rule" "egress_1" {
  1014    type = "egress"
  1015    protocol = "-1"
  1016    from_port = 0
  1017    to_port = 0
  1018    prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"]
  1019  	security_group_id = "${aws_security_group.egress.id}"
  1020  }
  1021  `
  1022  
  1023  const testAccAWSSecurityGroupRuleSelfInSource = `
  1024  resource "aws_vpc" "foo" {
  1025    cidr_block = "10.1.0.0/16"
  1026  
  1027    tags {
  1028      Name = "tf_sg_rule_self_group"
  1029    }
  1030  }
  1031  
  1032  resource "aws_security_group" "web" {
  1033    name        = "allow_all"
  1034    description = "Allow all inbound traffic"
  1035    vpc_id      = "${aws_vpc.foo.id}"
  1036  }
  1037  
  1038  resource "aws_security_group_rule" "allow_self" {
  1039    type                     = "ingress"
  1040    from_port                = 0
  1041    to_port                  = 0
  1042    protocol                 = "-1"
  1043    security_group_id        = "${aws_security_group.web.id}"
  1044    source_security_group_id = "${aws_security_group.web.id}"
  1045  }
  1046  `