github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_security_group_rule_test.go (about)

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