github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/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  	"regexp"
    16  )
    17  
    18  func TestIpPermissionIDHash(t *testing.T) {
    19  	simple := &ec2.IpPermission{
    20  		IpProtocol: aws.String("tcp"),
    21  		FromPort:   aws.Int64(int64(80)),
    22  		ToPort:     aws.Int64(int64(8000)),
    23  		IpRanges: []*ec2.IpRange{
    24  			{
    25  				CidrIp: aws.String("10.0.0.0/8"),
    26  			},
    27  		},
    28  	}
    29  
    30  	egress := &ec2.IpPermission{
    31  		IpProtocol: aws.String("tcp"),
    32  		FromPort:   aws.Int64(int64(80)),
    33  		ToPort:     aws.Int64(int64(8000)),
    34  		IpRanges: []*ec2.IpRange{
    35  			{
    36  				CidrIp: aws.String("10.0.0.0/8"),
    37  			},
    38  		},
    39  	}
    40  
    41  	egress_all := &ec2.IpPermission{
    42  		IpProtocol: aws.String("-1"),
    43  		IpRanges: []*ec2.IpRange{
    44  			{
    45  				CidrIp: aws.String("10.0.0.0/8"),
    46  			},
    47  		},
    48  	}
    49  
    50  	vpc_security_group_source := &ec2.IpPermission{
    51  		IpProtocol: aws.String("tcp"),
    52  		FromPort:   aws.Int64(int64(80)),
    53  		ToPort:     aws.Int64(int64(8000)),
    54  		UserIdGroupPairs: []*ec2.UserIdGroupPair{
    55  			&ec2.UserIdGroupPair{
    56  				UserId:  aws.String("987654321"),
    57  				GroupId: aws.String("sg-12345678"),
    58  			},
    59  			&ec2.UserIdGroupPair{
    60  				UserId:  aws.String("123456789"),
    61  				GroupId: aws.String("sg-987654321"),
    62  			},
    63  			&ec2.UserIdGroupPair{
    64  				UserId:  aws.String("123456789"),
    65  				GroupId: aws.String("sg-12345678"),
    66  			},
    67  		},
    68  	}
    69  
    70  	security_group_source := &ec2.IpPermission{
    71  		IpProtocol: aws.String("tcp"),
    72  		FromPort:   aws.Int64(int64(80)),
    73  		ToPort:     aws.Int64(int64(8000)),
    74  		UserIdGroupPairs: []*ec2.UserIdGroupPair{
    75  			&ec2.UserIdGroupPair{
    76  				UserId:    aws.String("987654321"),
    77  				GroupName: aws.String("my-security-group"),
    78  			},
    79  			&ec2.UserIdGroupPair{
    80  				UserId:    aws.String("123456789"),
    81  				GroupName: aws.String("my-security-group"),
    82  			},
    83  			&ec2.UserIdGroupPair{
    84  				UserId:    aws.String("123456789"),
    85  				GroupName: aws.String("my-other-security-group"),
    86  			},
    87  		},
    88  	}
    89  
    90  	// hardcoded hashes, to detect future change
    91  	cases := []struct {
    92  		Input  *ec2.IpPermission
    93  		Type   string
    94  		Output string
    95  	}{
    96  		{simple, "ingress", "sgrule-3403497314"},
    97  		{egress, "egress", "sgrule-1173186295"},
    98  		{egress_all, "egress", "sgrule-766323498"},
    99  		{vpc_security_group_source, "egress", "sgrule-351225364"},
   100  		{security_group_source, "egress", "sgrule-2198807188"},
   101  	}
   102  
   103  	for _, tc := range cases {
   104  		actual := ipPermissionIDHash("sg-12345", tc.Type, tc.Input)
   105  		if actual != tc.Output {
   106  			t.Errorf("input: %s - %s\noutput: %s", tc.Type, tc.Input, actual)
   107  		}
   108  	}
   109  }
   110  
   111  func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) {
   112  	var group ec2.SecurityGroup
   113  
   114  	testRuleCount := func(*terraform.State) error {
   115  		if len(group.IpPermissions) != 1 {
   116  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   117  				1, len(group.IpPermissions))
   118  		}
   119  
   120  		rule := group.IpPermissions[0]
   121  		if *rule.FromPort != int64(80) {
   122  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   123  				80, int(*rule.FromPort))
   124  		}
   125  
   126  		return nil
   127  	}
   128  
   129  	resource.Test(t, resource.TestCase{
   130  		PreCheck:     func() { testAccPreCheck(t) },
   131  		Providers:    testAccProviders,
   132  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   133  		Steps: []resource.TestStep{
   134  			{
   135  				Config: testAccAWSSecurityGroupRuleIngressConfig,
   136  				Check: resource.ComposeTestCheckFunc(
   137  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   138  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   139  					resource.TestCheckResourceAttr(
   140  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   141  					testRuleCount,
   142  				),
   143  			},
   144  		},
   145  	})
   146  }
   147  
   148  func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) {
   149  	var group ec2.SecurityGroup
   150  
   151  	testRuleCount := func(*terraform.State) error {
   152  		if len(group.IpPermissions) != 1 {
   153  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   154  				1, len(group.IpPermissions))
   155  		}
   156  
   157  		rule := group.IpPermissions[0]
   158  		if *rule.FromPort != int64(80) {
   159  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   160  				80, int(*rule.FromPort))
   161  		}
   162  
   163  		return nil
   164  	}
   165  
   166  	resource.Test(t, resource.TestCase{
   167  		PreCheck:     func() { testAccPreCheck(t) },
   168  		Providers:    testAccProviders,
   169  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   170  		Steps: []resource.TestStep{
   171  			{
   172  				Config: testAccAWSSecurityGroupRuleIngress_protocolConfig,
   173  				Check: resource.ComposeTestCheckFunc(
   174  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   175  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   176  					resource.TestCheckResourceAttr(
   177  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   178  					testRuleCount,
   179  				),
   180  			},
   181  		},
   182  	})
   183  }
   184  
   185  func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
   186  	var group ec2.SecurityGroup
   187  
   188  	testRuleCount := func(*terraform.State) error {
   189  		if len(group.IpPermissions) != 1 {
   190  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   191  				1, len(group.IpPermissions))
   192  		}
   193  
   194  		rule := group.IpPermissions[0]
   195  		if *rule.FromPort != int64(80) {
   196  			return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
   197  				80, int(*rule.FromPort))
   198  		}
   199  
   200  		return nil
   201  	}
   202  
   203  	resource.Test(t, resource.TestCase{
   204  		PreCheck:     func() { testAccPreCheck(t) },
   205  		Providers:    testAccProviders,
   206  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   207  		Steps: []resource.TestStep{
   208  			{
   209  				Config: testAccAWSSecurityGroupRuleIngressClassicConfig,
   210  				Check: resource.ComposeTestCheckFunc(
   211  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   212  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
   213  					resource.TestCheckResourceAttr(
   214  						"aws_security_group_rule.ingress_1", "from_port", "80"),
   215  					testRuleCount,
   216  				),
   217  			},
   218  		},
   219  	})
   220  }
   221  
   222  func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) {
   223  	var group ec2.SecurityGroup
   224  
   225  	testMultiRuleCount := func(*terraform.State) error {
   226  		if len(group.IpPermissions) != 2 {
   227  			return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
   228  				2, len(group.IpPermissions))
   229  		}
   230  
   231  		var rule *ec2.IpPermission
   232  		for _, r := range group.IpPermissions {
   233  			if *r.FromPort == int64(80) {
   234  				rule = r
   235  			}
   236  		}
   237  
   238  		if *rule.ToPort != int64(8000) {
   239  			return fmt.Errorf("Wrong Security Group port 2 setting, expected %d, got %d",
   240  				8000, int(*rule.ToPort))
   241  		}
   242  
   243  		return nil
   244  	}
   245  
   246  	resource.Test(t, resource.TestCase{
   247  		PreCheck:     func() { testAccPreCheck(t) },
   248  		Providers:    testAccProviders,
   249  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   250  		Steps: []resource.TestStep{
   251  			{
   252  				Config: testAccAWSSecurityGroupRuleConfigMultiIngress,
   253  				Check: resource.ComposeTestCheckFunc(
   254  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   255  					testMultiRuleCount,
   256  				),
   257  			},
   258  		},
   259  	})
   260  }
   261  
   262  func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
   263  	var group ec2.SecurityGroup
   264  
   265  	resource.Test(t, resource.TestCase{
   266  		PreCheck:     func() { testAccPreCheck(t) },
   267  		Providers:    testAccProviders,
   268  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   269  		Steps: []resource.TestStep{
   270  			{
   271  				Config: testAccAWSSecurityGroupRuleEgressConfig,
   272  				Check: resource.ComposeTestCheckFunc(
   273  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   274  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"),
   275  				),
   276  			},
   277  		},
   278  	})
   279  }
   280  
   281  func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) {
   282  	var group ec2.SecurityGroup
   283  
   284  	resource.Test(t, resource.TestCase{
   285  		PreCheck:     func() { testAccPreCheck(t) },
   286  		Providers:    testAccProviders,
   287  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   288  		Steps: []resource.TestStep{
   289  			{
   290  				Config: testAccAWSSecurityGroupRuleConfigSelfReference,
   291  				Check: resource.ComposeTestCheckFunc(
   292  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   293  				),
   294  			},
   295  		},
   296  	})
   297  }
   298  
   299  func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) {
   300  	resource.Test(t, resource.TestCase{
   301  		PreCheck:     func() { testAccPreCheck(t) },
   302  		Providers:    testAccProviders,
   303  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   304  		Steps: []resource.TestStep{
   305  			{
   306  				Config:      testAccAWSSecurityGroupRuleExpectInvalidType,
   307  				ExpectError: regexp.MustCompile(`\\"type\\" contains an invalid Security Group Rule type \\"foobar\\"`),
   308  			},
   309  		},
   310  	})
   311  }
   312  
   313  // testing partial match implementation
   314  func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
   315  	var group ec2.SecurityGroup
   316  
   317  	p := ec2.IpPermission{
   318  		FromPort:   aws.Int64(80),
   319  		ToPort:     aws.Int64(80),
   320  		IpProtocol: aws.String("tcp"),
   321  		IpRanges: []*ec2.IpRange{
   322  			{CidrIp: aws.String("10.0.2.0/24")},
   323  			{CidrIp: aws.String("10.0.3.0/24")},
   324  			{CidrIp: aws.String("10.0.4.0/24")},
   325  		},
   326  	}
   327  
   328  	o := ec2.IpPermission{
   329  		FromPort:   aws.Int64(80),
   330  		ToPort:     aws.Int64(80),
   331  		IpProtocol: aws.String("tcp"),
   332  		IpRanges: []*ec2.IpRange{
   333  			{CidrIp: aws.String("10.0.5.0/24")},
   334  		},
   335  	}
   336  
   337  	resource.Test(t, resource.TestCase{
   338  		PreCheck:     func() { testAccPreCheck(t) },
   339  		Providers:    testAccProviders,
   340  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   341  		Steps: []resource.TestStep{
   342  			{
   343  				Config: testAccAWSSecurityGroupRulePartialMatching,
   344  				Check: resource.ComposeTestCheckFunc(
   345  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   346  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"),
   347  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.other", &group, &o, "ingress"),
   348  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"),
   349  				),
   350  			},
   351  		},
   352  	})
   353  }
   354  
   355  func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
   356  	var group ec2.SecurityGroup
   357  	var nat ec2.SecurityGroup
   358  	var p ec2.IpPermission
   359  
   360  	// This function creates the expected IPPermission with the group id from an
   361  	// external security group, needed because Security Group IDs are generated on
   362  	// AWS side and can't be known ahead of time.
   363  	setupSG := func(*terraform.State) error {
   364  		if nat.GroupId == nil {
   365  			return fmt.Errorf("Error: nat group has nil GroupID")
   366  		}
   367  
   368  		p = ec2.IpPermission{
   369  			FromPort:   aws.Int64(80),
   370  			ToPort:     aws.Int64(80),
   371  			IpProtocol: aws.String("tcp"),
   372  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   373  				&ec2.UserIdGroupPair{GroupId: nat.GroupId},
   374  			},
   375  		}
   376  
   377  		return nil
   378  	}
   379  
   380  	resource.Test(t, resource.TestCase{
   381  		PreCheck:     func() { testAccPreCheck(t) },
   382  		Providers:    testAccProviders,
   383  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   384  		Steps: []resource.TestStep{
   385  			{
   386  				Config: testAccAWSSecurityGroupRulePartialMatching_Source,
   387  				Check: resource.ComposeTestCheckFunc(
   388  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   389  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat),
   390  					setupSG,
   391  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"),
   392  				),
   393  			},
   394  		},
   395  	})
   396  }
   397  
   398  func TestAccAWSSecurityGroupRule_Issue5310(t *testing.T) {
   399  	var group ec2.SecurityGroup
   400  
   401  	resource.Test(t, resource.TestCase{
   402  		PreCheck:     func() { testAccPreCheck(t) },
   403  		Providers:    testAccProviders,
   404  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   405  		Steps: []resource.TestStep{
   406  			{
   407  				Config: testAccAWSSecurityGroupRuleIssue5310,
   408  				Check: resource.ComposeTestCheckFunc(
   409  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group),
   410  				),
   411  			},
   412  		},
   413  	})
   414  }
   415  
   416  func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
   417  	var group ec2.SecurityGroup
   418  
   419  	resource.Test(t, resource.TestCase{
   420  		PreCheck:     func() { testAccPreCheck(t) },
   421  		Providers:    testAccProviders,
   422  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   423  		Steps: []resource.TestStep{
   424  			{
   425  				Config: testAccAWSSecurityGroupRuleRace,
   426  				Check: resource.ComposeTestCheckFunc(
   427  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group),
   428  				),
   429  			},
   430  		},
   431  	})
   432  }
   433  
   434  func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) {
   435  	var group ec2.SecurityGroup
   436  
   437  	resource.Test(t, resource.TestCase{
   438  		PreCheck:     func() { testAccPreCheck(t) },
   439  		Providers:    testAccProviders,
   440  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   441  		Steps: []resource.TestStep{
   442  			{
   443  				Config: testAccAWSSecurityGroupRuleSelfInSource,
   444  				Check: resource.ComposeTestCheckFunc(
   445  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
   446  				),
   447  			},
   448  		},
   449  	})
   450  }
   451  
   452  func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) {
   453  	var group ec2.SecurityGroup
   454  	var endpoint ec2.VpcEndpoint
   455  	var p ec2.IpPermission
   456  
   457  	// This function creates the expected IPPermission with the prefix list ID from
   458  	// the VPC Endpoint created in the test
   459  	setupSG := func(*terraform.State) error {
   460  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   461  		prefixListInput := &ec2.DescribePrefixListsInput{
   462  			Filters: []*ec2.Filter{
   463  				{Name: aws.String("prefix-list-name"), Values: []*string{endpoint.ServiceName}},
   464  			},
   465  		}
   466  
   467  		log.Printf("[DEBUG] Reading VPC Endpoint prefix list: %s", prefixListInput)
   468  		prefixListsOutput, err := conn.DescribePrefixLists(prefixListInput)
   469  
   470  		if err != nil {
   471  			_, ok := err.(awserr.Error)
   472  			if !ok {
   473  				return fmt.Errorf("Error reading VPC Endpoint prefix list: %s", err.Error())
   474  			}
   475  		}
   476  
   477  		if len(prefixListsOutput.PrefixLists) != 1 {
   478  			return fmt.Errorf("There are multiple prefix lists associated with the service name '%s'. Unexpected", prefixListsOutput)
   479  		}
   480  
   481  		p = ec2.IpPermission{
   482  			IpProtocol: aws.String("-1"),
   483  			PrefixListIds: []*ec2.PrefixListId{
   484  				{PrefixListId: prefixListsOutput.PrefixLists[0].PrefixListId},
   485  			},
   486  		}
   487  
   488  		return nil
   489  	}
   490  
   491  	resource.Test(t, resource.TestCase{
   492  		PreCheck:     func() { testAccPreCheck(t) },
   493  		Providers:    testAccProviders,
   494  		CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
   495  		Steps: []resource.TestStep{
   496  			{
   497  				Config: testAccAWSSecurityGroupRulePrefixListEgressConfig,
   498  				Check: resource.ComposeTestCheckFunc(
   499  					testAccCheckAWSSecurityGroupRuleExists("aws_security_group.egress", &group),
   500  					// lookup info on the VPC Endpoint created, to populate the expected
   501  					// IP Perm
   502  					testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3-us-west-2", &endpoint),
   503  					setupSG,
   504  					testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"),
   505  				),
   506  			},
   507  		},
   508  	})
   509  }
   510  
   511  func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
   512  	conn := testAccProvider.Meta().(*AWSClient).ec2conn
   513  
   514  	for _, rs := range s.RootModule().Resources {
   515  		if rs.Type != "aws_security_group" {
   516  			continue
   517  		}
   518  
   519  		// Retrieve our group
   520  		req := &ec2.DescribeSecurityGroupsInput{
   521  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   522  		}
   523  		resp, err := conn.DescribeSecurityGroups(req)
   524  		if err == nil {
   525  			if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   526  				return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
   527  			}
   528  
   529  			return nil
   530  		}
   531  
   532  		ec2err, ok := err.(awserr.Error)
   533  		if !ok {
   534  			return err
   535  		}
   536  		// Confirm error code is what we want
   537  		if ec2err.Code() != "InvalidGroup.NotFound" {
   538  			return err
   539  		}
   540  	}
   541  
   542  	return nil
   543  }
   544  
   545  func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc {
   546  	return func(s *terraform.State) error {
   547  		rs, ok := s.RootModule().Resources[n]
   548  		if !ok {
   549  			return fmt.Errorf("Not found: %s", n)
   550  		}
   551  
   552  		if rs.Primary.ID == "" {
   553  			return fmt.Errorf("No Security Group is set")
   554  		}
   555  
   556  		conn := testAccProvider.Meta().(*AWSClient).ec2conn
   557  		req := &ec2.DescribeSecurityGroupsInput{
   558  			GroupIds: []*string{aws.String(rs.Primary.ID)},
   559  		}
   560  		resp, err := conn.DescribeSecurityGroups(req)
   561  		if err != nil {
   562  			return err
   563  		}
   564  
   565  		if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
   566  			*group = *resp.SecurityGroups[0]
   567  			return nil
   568  		}
   569  
   570  		return fmt.Errorf("Security Group not found")
   571  	}
   572  }
   573  
   574  func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
   575  	return func(s *terraform.State) error {
   576  		rs, ok := s.RootModule().Resources[n]
   577  		if !ok {
   578  			return fmt.Errorf("Security Group Rule Not found: %s", n)
   579  		}
   580  
   581  		if rs.Primary.ID == "" {
   582  			return fmt.Errorf("No Security Group Rule is set")
   583  		}
   584  
   585  		if p == nil {
   586  			p = &ec2.IpPermission{
   587  				FromPort:   aws.Int64(80),
   588  				ToPort:     aws.Int64(8000),
   589  				IpProtocol: aws.String("tcp"),
   590  				IpRanges:   []*ec2.IpRange{{CidrIp: aws.String("10.0.0.0/8")}},
   591  			}
   592  		}
   593  
   594  		var matchingRule *ec2.IpPermission
   595  		var rules []*ec2.IpPermission
   596  		if ruleType == "ingress" {
   597  			rules = group.IpPermissions
   598  		} else {
   599  			rules = group.IpPermissionsEgress
   600  		}
   601  
   602  		if len(rules) == 0 {
   603  			return fmt.Errorf("No IPPerms")
   604  		}
   605  
   606  		for _, r := range rules {
   607  			if r.ToPort != nil && *p.ToPort != *r.ToPort {
   608  				continue
   609  			}
   610  
   611  			if r.FromPort != nil && *p.FromPort != *r.FromPort {
   612  				continue
   613  			}
   614  
   615  			if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
   616  				continue
   617  			}
   618  
   619  			remaining := len(p.IpRanges)
   620  			for _, ip := range p.IpRanges {
   621  				for _, rip := range r.IpRanges {
   622  					if *ip.CidrIp == *rip.CidrIp {
   623  						remaining--
   624  					}
   625  				}
   626  			}
   627  
   628  			if remaining > 0 {
   629  				continue
   630  			}
   631  
   632  			remaining = len(p.UserIdGroupPairs)
   633  			for _, ip := range p.UserIdGroupPairs {
   634  				for _, rip := range r.UserIdGroupPairs {
   635  					if *ip.GroupId == *rip.GroupId {
   636  						remaining--
   637  					}
   638  				}
   639  			}
   640  
   641  			if remaining > 0 {
   642  				continue
   643  			}
   644  
   645  			remaining = len(p.PrefixListIds)
   646  			for _, pip := range p.PrefixListIds {
   647  				for _, rpip := range r.PrefixListIds {
   648  					if *pip.PrefixListId == *rpip.PrefixListId {
   649  						remaining--
   650  					}
   651  				}
   652  			}
   653  
   654  			if remaining > 0 {
   655  				continue
   656  			}
   657  
   658  			matchingRule = r
   659  		}
   660  
   661  		if matchingRule != nil {
   662  			log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
   663  			return nil
   664  		}
   665  
   666  		return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
   667  	}
   668  }
   669  
   670  const testAccAWSSecurityGroupRuleIngressConfig = `
   671  resource "aws_security_group" "web" {
   672    name = "terraform_acceptance_test_example"
   673    description = "Used in the terraform acceptance tests"
   674  
   675          tags {
   676                  Name = "tf-acc-test"
   677          }
   678  }
   679  
   680  resource "aws_security_group_rule" "ingress_1" {
   681    type = "ingress"
   682    protocol = "tcp"
   683    from_port = 80
   684    to_port = 8000
   685    cidr_blocks = ["10.0.0.0/8"]
   686  
   687    security_group_id = "${aws_security_group.web.id}"
   688  }
   689  `
   690  
   691  const testAccAWSSecurityGroupRuleIngress_protocolConfig = `
   692  resource "aws_vpc" "tftest" {
   693    cidr_block = "10.0.0.0/16"
   694  
   695    tags {
   696      Name = "tf-testing"
   697    }
   698  }
   699  
   700  resource "aws_security_group" "web" {
   701    vpc_id = "${aws_vpc.tftest.id}"
   702  
   703    tags {
   704      Name = "tf-acc-test"
   705    }
   706  }
   707  
   708  resource "aws_security_group_rule" "ingress_1" {
   709    type        = "ingress"
   710    protocol    = "6"
   711    from_port   = 80
   712    to_port     = 8000
   713    cidr_blocks = ["10.0.0.0/8"]
   714  
   715    security_group_id = "${aws_security_group.web.id}"
   716  }
   717  
   718  `
   719  
   720  const testAccAWSSecurityGroupRuleIssue5310 = `
   721  provider "aws" {
   722          region = "us-east-1"
   723  }
   724  
   725  resource "aws_security_group" "issue_5310" {
   726      name = "terraform-test-issue_5310"
   727      description = "SG for test of issue 5310"
   728  }
   729  
   730  resource "aws_security_group_rule" "issue_5310" {
   731      type = "ingress"
   732      from_port = 0
   733      to_port = 65535
   734      protocol = "tcp"
   735      security_group_id = "${aws_security_group.issue_5310.id}"
   736      self = true
   737  }
   738  `
   739  
   740  const testAccAWSSecurityGroupRuleIngressClassicConfig = `
   741  provider "aws" {
   742          region = "us-east-1"
   743  }
   744  
   745  resource "aws_security_group" "web" {
   746    name = "terraform_acceptance_test_example"
   747    description = "Used in the terraform acceptance tests"
   748  
   749          tags {
   750                  Name = "tf-acc-test"
   751          }
   752  }
   753  
   754  resource "aws_security_group_rule" "ingress_1" {
   755    type = "ingress"
   756    protocol = "tcp"
   757    from_port = 80
   758    to_port = 8000
   759    cidr_blocks = ["10.0.0.0/8"]
   760  
   761    security_group_id = "${aws_security_group.web.id}"
   762  }
   763  `
   764  
   765  const testAccAWSSecurityGroupRuleEgressConfig = `
   766  resource "aws_security_group" "web" {
   767    name = "terraform_acceptance_test_example"
   768    description = "Used in the terraform acceptance tests"
   769  
   770          tags {
   771                  Name = "tf-acc-test"
   772          }
   773  }
   774  
   775  resource "aws_security_group_rule" "egress_1" {
   776    type = "egress"
   777    protocol = "tcp"
   778    from_port = 80
   779    to_port = 8000
   780    cidr_blocks = ["10.0.0.0/8"]
   781  
   782    security_group_id = "${aws_security_group.web.id}"
   783  }
   784  `
   785  
   786  const testAccAWSSecurityGroupRuleConfigMultiIngress = `
   787  resource "aws_security_group" "web" {
   788    name = "terraform_acceptance_test_example_2"
   789    description = "Used in the terraform acceptance tests"
   790  }
   791  
   792  resource "aws_security_group" "worker" {
   793    name = "terraform_acceptance_test_example_worker"
   794    description = "Used in the terraform acceptance tests"
   795  }
   796  
   797  
   798  resource "aws_security_group_rule" "ingress_1" {
   799    type = "ingress"
   800    protocol = "tcp"
   801    from_port = 22
   802    to_port = 22
   803    cidr_blocks = ["10.0.0.0/8"]
   804  
   805    security_group_id = "${aws_security_group.web.id}"
   806  }
   807  
   808  resource "aws_security_group_rule" "ingress_2" {
   809    type = "ingress"
   810    protocol = "tcp"
   811    from_port = 80
   812    to_port = 8000
   813          self = true
   814  
   815    security_group_id = "${aws_security_group.web.id}"
   816  }
   817  `
   818  
   819  // check for GH-1985 regression
   820  const testAccAWSSecurityGroupRuleConfigSelfReference = `
   821  provider "aws" {
   822    region = "us-west-2"
   823  }
   824  
   825  resource "aws_vpc" "main" {
   826    cidr_block = "10.0.0.0/16"
   827    tags {
   828      Name = "sg-self-test"
   829    }
   830  }
   831  
   832  resource "aws_security_group" "web" {
   833    name = "main"
   834    vpc_id = "${aws_vpc.main.id}"
   835    tags {
   836      Name = "sg-self-test"
   837    }
   838  }
   839  
   840  resource "aws_security_group_rule" "self" {
   841    type = "ingress"
   842    protocol = "-1"
   843    from_port = 0
   844    to_port = 0
   845    self = true
   846    security_group_id = "${aws_security_group.web.id}"
   847  }
   848  `
   849  
   850  const testAccAWSSecurityGroupRulePartialMatching = `
   851  resource "aws_vpc" "default" {
   852    cidr_block = "10.0.0.0/16"
   853    tags {
   854      Name = "tf-sg-rule-bug"
   855    }
   856  }
   857  
   858  resource "aws_security_group" "web" {
   859      name = "tf-other"
   860      vpc_id = "${aws_vpc.default.id}"
   861      tags {
   862          Name        = "tf-other-sg"
   863      }
   864  }
   865  
   866  resource "aws_security_group" "nat" {
   867      name = "tf-nat"
   868      vpc_id = "${aws_vpc.default.id}"
   869      tags {
   870          Name        = "tf-nat-sg"
   871      }
   872  }
   873  
   874  resource "aws_security_group_rule" "ingress" {
   875      type        = "ingress"
   876      from_port   = 80
   877      to_port     = 80
   878      protocol    = "tcp"
   879      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   880  
   881     security_group_id = "${aws_security_group.web.id}"
   882  }
   883  
   884  resource "aws_security_group_rule" "other" {
   885      type        = "ingress"
   886      from_port   = 80
   887      to_port     = 80
   888      protocol    = "tcp"
   889      cidr_blocks = ["10.0.5.0/24"]
   890  
   891     security_group_id = "${aws_security_group.web.id}"
   892  }
   893  
   894  // same a above, but different group, to guard against bad hashing
   895  resource "aws_security_group_rule" "nat_ingress" {
   896      type        = "ingress"
   897      from_port   = 80
   898      to_port     = 80
   899      protocol    = "tcp"
   900      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   901  
   902     security_group_id = "${aws_security_group.nat.id}"
   903  }
   904  `
   905  
   906  const testAccAWSSecurityGroupRulePartialMatching_Source = `
   907  resource "aws_vpc" "default" {
   908    cidr_block = "10.0.0.0/16"
   909    tags {
   910      Name = "tf-sg-rule-bug"
   911    }
   912  }
   913  
   914  resource "aws_security_group" "web" {
   915      name = "tf-other"
   916      vpc_id = "${aws_vpc.default.id}"
   917      tags {
   918          Name        = "tf-other-sg"
   919      }
   920  }
   921  
   922  resource "aws_security_group" "nat" {
   923      name = "tf-nat"
   924      vpc_id = "${aws_vpc.default.id}"
   925      tags {
   926          Name        = "tf-nat-sg"
   927      }
   928  }
   929  
   930  resource "aws_security_group_rule" "source_ingress" {
   931      type        = "ingress"
   932      from_port   = 80
   933      to_port     = 80
   934      protocol    = "tcp"
   935  
   936                  source_security_group_id = "${aws_security_group.nat.id}"
   937     security_group_id = "${aws_security_group.web.id}"
   938  }
   939  
   940  resource "aws_security_group_rule" "other_ingress" {
   941      type        = "ingress"
   942      from_port   = 80
   943      to_port     = 80
   944      protocol    = "tcp"
   945      cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
   946  
   947     security_group_id = "${aws_security_group.web.id}"
   948  }
   949  `
   950  
   951  var testAccAWSSecurityGroupRuleRace = func() string {
   952  	var b bytes.Buffer
   953  	iterations := 50
   954  	b.WriteString(fmt.Sprintf(`
   955  		resource "aws_vpc" "default" {
   956  			cidr_block = "10.0.0.0/16"
   957  			tags { Name = "tf-sg-rule-race" }
   958  		}
   959  
   960  		resource "aws_security_group" "race" {
   961  			name   = "tf-sg-rule-race-group-%d"
   962  			vpc_id = "${aws_vpc.default.id}"
   963  		}
   964  	`, acctest.RandInt()))
   965  	for i := 1; i < iterations; i++ {
   966  		b.WriteString(fmt.Sprintf(`
   967  			resource "aws_security_group_rule" "ingress%d" {
   968  				security_group_id = "${aws_security_group.race.id}"
   969  				type              = "ingress"
   970  				from_port         = %d
   971  				to_port           = %d
   972  				protocol          = "tcp"
   973  				cidr_blocks       = ["10.0.0.%d/32"]
   974  			}
   975  
   976  			resource "aws_security_group_rule" "egress%d" {
   977  				security_group_id = "${aws_security_group.race.id}"
   978  				type              = "egress"
   979  				from_port         = %d
   980  				to_port           = %d
   981  				protocol          = "tcp"
   982  				cidr_blocks       = ["10.0.0.%d/32"]
   983  			}
   984  		`, i, i, i, i, i, i, i, i))
   985  	}
   986  	return b.String()
   987  }()
   988  
   989  const testAccAWSSecurityGroupRulePrefixListEgressConfig = `
   990  
   991  resource "aws_vpc" "tf_sg_prefix_list_egress_test" {
   992      cidr_block = "10.0.0.0/16"
   993      tags {
   994              Name = "tf_sg_prefix_list_egress_test"
   995      }
   996  }
   997  
   998  resource "aws_route_table" "default" {
   999      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
  1000  }
  1001  
  1002  resource "aws_vpc_endpoint" "s3-us-west-2" {
  1003    	vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
  1004    	service_name = "com.amazonaws.us-west-2.s3"
  1005    	route_table_ids = ["${aws_route_table.default.id}"]
  1006    	policy = <<POLICY
  1007  {
  1008  	"Version": "2012-10-17",
  1009  	"Statement": [
  1010  		{
  1011  			"Sid":"AllowAll",
  1012  			"Effect":"Allow",
  1013  			"Principal":"*",
  1014  			"Action":"*",
  1015  			"Resource":"*"
  1016  		}
  1017  	]
  1018  }
  1019  POLICY
  1020  }
  1021  
  1022  resource "aws_security_group" "egress" {
  1023      name = "terraform_acceptance_test_prefix_list_egress"
  1024      description = "Used in the terraform acceptance tests"
  1025      vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
  1026  }
  1027  
  1028  resource "aws_security_group_rule" "egress_1" {
  1029    type = "egress"
  1030    protocol = "-1"
  1031    from_port = 0
  1032    to_port = 0
  1033    prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"]
  1034  	security_group_id = "${aws_security_group.egress.id}"
  1035  }
  1036  `
  1037  
  1038  const testAccAWSSecurityGroupRuleSelfInSource = `
  1039  resource "aws_vpc" "foo" {
  1040    cidr_block = "10.1.0.0/16"
  1041  
  1042    tags {
  1043      Name = "tf_sg_rule_self_group"
  1044    }
  1045  }
  1046  
  1047  resource "aws_security_group" "web" {
  1048    name        = "allow_all"
  1049    description = "Allow all inbound traffic"
  1050    vpc_id      = "${aws_vpc.foo.id}"
  1051  }
  1052  
  1053  resource "aws_security_group_rule" "allow_self" {
  1054    type                     = "ingress"
  1055    from_port                = 0
  1056    to_port                  = 0
  1057    protocol                 = "-1"
  1058    security_group_id        = "${aws_security_group.web.id}"
  1059    source_security_group_id = "${aws_security_group.web.id}"
  1060  }
  1061  `
  1062  
  1063  const testAccAWSSecurityGroupRuleExpectInvalidType = `
  1064  resource "aws_vpc" "foo" {
  1065    cidr_block = "10.1.0.0/16"
  1066  
  1067    tags {
  1068      Name = "tf_sg_rule_self_group"
  1069    }
  1070  }
  1071  
  1072  resource "aws_security_group" "web" {
  1073    name        = "allow_all"
  1074    description = "Allow all inbound traffic"
  1075    vpc_id      = "${aws_vpc.foo.id}"
  1076  }
  1077  
  1078  resource "aws_security_group_rule" "allow_self" {
  1079    type                     = "foobar"
  1080    from_port                = 0
  1081    to_port                  = 0
  1082    protocol                 = "-1"
  1083    security_group_id        = "${aws_security_group.web.id}"
  1084    source_security_group_id = "${aws_security_group.web.id}"
  1085  }
  1086  `