diff --git a/aws/resource_aws_security_group_rule.go b/aws/resource_aws_security_group_rule.go index b7de49b80165..fcbbe3f0a3be 100644 --- a/aws/resource_aws_security_group_rule.go +++ b/aws/resource_aws_security_group_rule.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "sort" + "strconv" "strings" "time" @@ -23,6 +24,25 @@ func resourceAwsSecurityGroupRule() *schema.Resource { Read: resourceAwsSecurityGroupRuleRead, Update: resourceAwsSecurityGroupRuleUpdate, Delete: resourceAwsSecurityGroupRuleDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + importParts, err := validateSecurityGroupRuleImportString(d.Id()) + if err != nil { + return nil, err + } + if err := populateSecurityGroupRuleFromImport(d, importParts); err != nil { + return nil, err + } + err = resourceAwsSecurityGroupRuleRead(d, meta) + if err != nil { + return nil, err + } + + results := make([]*schema.ResourceData, 1) + results[0] = d + return results, nil + }, + }, SchemaVersion: 2, MigrateState: resourceAwsSecurityGroupRuleMigrateState, @@ -256,6 +276,7 @@ func resourceAwsSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) default: rules = sg.IpPermissionsEgress } + log.Printf("[DEBUG] Rules %v", rules) p, err := expandIPPerm(d, sg) if err != nil { @@ -287,6 +308,12 @@ func resourceAwsSecurityGroupRuleRead(d *schema.ResourceData, meta interface{}) d.Set("description", descriptionFromIPPerm(d, rule)) + if strings.Contains(d.Id(), "_") { + // import so fix the id + id := ipPermissionIDHash(sg_id, ruleType, p) + d.SetId(id) + } + return nil } @@ -845,3 +872,104 @@ func resourceSecurityGroupRuleDescriptionUpdate(conn *ec2.EC2, d *schema.Resourc return nil } + +// validateSecurityGroupRuleImportString does minimal validation of import string without going to AWS +func validateSecurityGroupRuleImportString(importStr string) ([]string, error) { + // example: sg-09a093729ef9382a6_ingress_tcp_8000_8000_10.0.3.0/24 + // example: sg-09a093729ef9382a6_ingress_92_0_65536_10.0.3.0/24_10.0.4.0/24 + // example: sg-09a093729ef9382a6_egress_tcp_8000_8000_10.0.3.0/24 + // example: sg-09a093729ef9382a6_egress_tcp_8000_8000_pl-34800000 + // example: sg-09a093729ef9382a6_ingress_all_0_65536_sg-08123412342323 + // example: sg-09a093729ef9382a6_ingress_tcp_100_121_10.1.0.0/16_2001:db8::/48_10.2.0.0/16_2002:db8::/48 + + log.Printf("[DEBUG] Validating import string %s", importStr) + + importParts := strings.Split(strings.ToLower(importStr), "_") + errStr := "unexpected format of import string (%q), expected SECURITYGROUPID_TYPE_PROTOCOL_FROMPORT_TOPORT_SOURCE[_SOURCE]*: %s" + if len(importParts) < 6 { + return nil, fmt.Errorf(errStr, importStr, "too few parts") + } + + sgID := importParts[0] + ruleType := importParts[1] + protocol := importParts[2] + fromPort := importParts[3] + toPort := importParts[4] + sources := importParts[5:] + + if !strings.HasPrefix(sgID, "sg-") { + return nil, fmt.Errorf(errStr, importStr, "invalid security group ID") + } + + if ruleType != "ingress" && ruleType != "egress" { + return nil, fmt.Errorf(errStr, importStr, "expecting 'ingress' or 'egress'") + } + + if _, ok := sgProtocolIntegers()[protocol]; !ok { + if _, err := strconv.Atoi(protocol); err != nil { + return nil, fmt.Errorf(errStr, importStr, "protocol must be tcp/udp/icmp/all or a number") + } + } + + if p1, err := strconv.Atoi(fromPort); err != nil { + return nil, fmt.Errorf(errStr, importStr, "invalid port") + } else if p2, err := strconv.Atoi(toPort); err != nil || p2 < p1 { + return nil, fmt.Errorf(errStr, importStr, "invalid port") + } + + for _, source := range sources { + // will be properly validated later + if source != "self" && !strings.Contains(source, "sg-") && !strings.Contains(source, "pl-") && !strings.Contains(source, ":") && !strings.Contains(source, ".") { + return nil, fmt.Errorf(errStr, importStr, "source must be cidr, ipv6cidr, prefix list, 'self', or a sg ID") + } + } + + log.Printf("[DEBUG] Validated import string %s", importStr) + return importParts, nil +} + +func populateSecurityGroupRuleFromImport(d *schema.ResourceData, importParts []string) error { + log.Printf("[DEBUG] Populating resource data on import: %v", importParts) + + sgID := importParts[0] + ruleType := importParts[1] + protocol := importParts[2] + fromPort, _ := strconv.Atoi(importParts[3]) + toPort, _ := strconv.Atoi(importParts[4]) + sources := importParts[5:] + + d.Set("security_group_id", sgID) + + if ruleType == "ingress" { + d.Set("type", ruleType) + } else { + d.Set("type", "egress") + } + + d.Set("protocol", protocolForValue(protocol)) + d.Set("from_port", fromPort) + d.Set("to_port", toPort) + + d.Set("self", false) + var cidrs []string + var prefixList []string + var ipv6cidrs []string + for _, source := range sources { + if source == "self" { + d.Set("self", true) + } else if strings.Contains(source, "sg-") { + d.Set("source_security_group_id", source) + } else if strings.Contains(source, "pl-") { + prefixList = append(prefixList, source) + } else if strings.Contains(source, ":") { + ipv6cidrs = append(ipv6cidrs, source) + } else { + cidrs = append(cidrs, source) + } + } + d.Set("ipv6_cidr_blocks", ipv6cidrs) + d.Set("cidr_blocks", cidrs) + d.Set("prefix_list_ids", prefixList) + + return nil +} diff --git a/aws/resource_aws_security_group_rule_test.go b/aws/resource_aws_security_group_rule_test.go index 8c61f225d689..20b46c09d9cf 100644 --- a/aws/resource_aws_security_group_rule_test.go +++ b/aws/resource_aws_security_group_rule_test.go @@ -5,6 +5,8 @@ import ( "fmt" "log" "regexp" + "strconv" + "strings" "testing" "github.com/aws/aws-sdk-go/aws" @@ -142,6 +144,12 @@ func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) { testRuleCount, ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -179,6 +187,12 @@ func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) { testRuleCount, ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -219,6 +233,12 @@ func TestAccAWSSecurityGroupRule_Ingress_Ipv6(t *testing.T) { testRuleCount, ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -257,6 +277,12 @@ func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) { testRuleCount, ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -297,6 +323,12 @@ func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) { testMultiRuleCount, ), }, + { + ResourceName: "aws_security_group_rule.ingress_2", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_2"), + ImportStateVerify: true, + }, }, }) } @@ -317,6 +349,12 @@ func TestAccAWSSecurityGroupRule_Egress(t *testing.T) { testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"), ), }, + { + ResourceName: "aws_security_group_rule.egress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_1"), + ImportStateVerify: true, + }, }, }) } @@ -335,6 +373,12 @@ func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) { testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), ), }, + { + ResourceName: "aws_security_group_rule.self", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.self"), + ImportStateVerify: true, + }, }, }) } @@ -412,6 +456,24 @@ func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) { testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"), ), }, + { + ResourceName: "aws_security_group_rule.ingress", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.other", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.other"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.nat_ingress", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.nat_ingress"), + ImportStateVerify: true, + }, }, }) } @@ -456,6 +518,12 @@ func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) { testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"), ), }, + { + ResourceName: "aws_security_group_rule.source_ingress", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.source_ingress"), + ImportStateVerify: true, + }, }, }) } @@ -474,6 +542,12 @@ func TestAccAWSSecurityGroupRule_Issue5310(t *testing.T) { testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group), ), }, + { + ResourceName: "aws_security_group_rule.issue_5310", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.issue_5310"), + ImportStateVerify: true, + }, }, }) } @@ -511,6 +585,12 @@ func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) { testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), ), }, + { + ResourceName: "aws_security_group_rule.allow_self", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.allow_self"), + ImportStateVerify: true, + }, }, }) } @@ -570,6 +650,12 @@ func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) { testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"), ), }, + { + ResourceName: "aws_security_group_rule.egress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_1"), + ImportStateVerify: true, + }, }, }) } @@ -591,6 +677,12 @@ func TestAccAWSSecurityGroupRule_IngressDescription(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.ingress_1", "description", "TF acceptance test ingress rule"), ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -612,6 +704,12 @@ func TestAccAWSSecurityGroupRule_EgressDescription(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.egress_1", "description", "TF acceptance test egress rule"), ), }, + { + ResourceName: "aws_security_group_rule.egress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_1"), + ImportStateVerify: true, + }, }, }) } @@ -642,6 +740,12 @@ func TestAccAWSSecurityGroupRule_IngressDescription_updates(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.ingress_1", "description", "TF acceptance test ingress rule updated"), ), }, + { + ResourceName: "aws_security_group_rule.ingress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_1"), + ImportStateVerify: true, + }, }, }) } @@ -672,6 +776,12 @@ func TestAccAWSSecurityGroupRule_EgressDescription_updates(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.egress_1", "description", "TF acceptance test egress rule updated"), ), }, + { + ResourceName: "aws_security_group_rule.egress_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_1"), + ImportStateVerify: true, + }, }, }) } @@ -783,6 +893,24 @@ func TestAccAWSSecurityGroupRule_MultiDescription(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.ingress_rule_3", "description", "NAT SG Description"), ), }, + { + ResourceName: "aws_security_group_rule.ingress_rule_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_rule_1"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.ingress_rule_2", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_rule_2"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.ingress_rule_3", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.ingress_rule_3"), + ImportStateVerify: true, + }, { Config: testAccAWSSecurityGroupRuleMultiDescription(rInt, "egress"), Check: resource.ComposeTestCheckFunc( @@ -805,6 +933,30 @@ func TestAccAWSSecurityGroupRule_MultiDescription(t *testing.T) { resource.TestCheckResourceAttr("aws_security_group_rule.egress_rule_4", "description", "Prefix List Description"), ), }, + { + ResourceName: "aws_security_group_rule.egress_rule_1", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_rule_1"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.egress_rule_2", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_rule_2"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.egress_rule_3", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_rule_3"), + ImportStateVerify: true, + }, + { + ResourceName: "aws_security_group_rule.egress_rule_4", + ImportState: true, + ImportStateIdFunc: testAccAWSSecurityGroupRuleImportStateIdFunc("aws_security_group_rule.egress_rule_4"), + ImportStateVerify: true, + }, }, }) } @@ -981,26 +1133,91 @@ func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGro } } +func testAccAWSSecurityGroupRuleImportStateIdFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + + sgID := rs.Primary.Attributes["security_group_id"] + ruleType := rs.Primary.Attributes["type"] + protocol := rs.Primary.Attributes["protocol"] + fromPort := rs.Primary.Attributes["from_port"] + toPort := rs.Primary.Attributes["to_port"] + + cidrs, err := testAccAWSSecurityGroupRuleImportGetAttrs(rs.Primary.Attributes, "cidr_blocks") + if err != nil { + return "", err + } + + ipv6CIDRs, err := testAccAWSSecurityGroupRuleImportGetAttrs(rs.Primary.Attributes, "ipv6_cidr_blocks") + if err != nil { + return "", err + } + + prefixes, err := testAccAWSSecurityGroupRuleImportGetAttrs(rs.Primary.Attributes, "prefix_list_ids") + if err != nil { + return "", err + } + + var parts []string + parts = append(parts, sgID) + parts = append(parts, ruleType) + parts = append(parts, protocol) + parts = append(parts, fromPort) + parts = append(parts, toPort) + parts = append(parts, *cidrs...) + parts = append(parts, *ipv6CIDRs...) + parts = append(parts, *prefixes...) + + if sgSource, ok := rs.Primary.Attributes["source_security_group_id"]; ok { + parts = append(parts, sgSource) + } + + if rs.Primary.Attributes["self"] == "true" { + parts = append(parts, "self") + } + + return strings.Join(parts, "_"), nil + } +} + +func testAccAWSSecurityGroupRuleImportGetAttrs(attrs map[string]string, key string) (*[]string, error) { + var values []string + if countStr, ok := attrs[fmt.Sprintf("%s.#", key)]; ok && countStr != "0" { + count, err := strconv.Atoi(countStr) + if err != nil { + return nil, err + } + for i := 0; i < count; i++ { + values = append(values, attrs[fmt.Sprintf("%s.%d", key, i)]) + } + } + return &values, nil +} + func testAccAWSSecurityGroupRuleIngressConfig(rInt int) string { return fmt.Sprintf(` - resource "aws_security_group" "web" { - name = "terraform_test_%d" - description = "Used in the terraform acceptance tests" +resource "aws_security_group" "web" { + name = "terraform_test_%d" + description = "Used in the terraform acceptance tests" - tags { - Name = "tf-acc-test" - } - } + tags { + Name = "tf-acc-test" + } +} - resource "aws_security_group_rule" "ingress_1" { - type = "ingress" - protocol = "tcp" - from_port = 80 - to_port = 8000 - cidr_blocks = ["10.0.0.0/8"] +resource "aws_security_group_rule" "ingress_1" { + type = "ingress" + protocol = "tcp" + from_port = 80 + to_port = 8000 + cidr_blocks = ["10.0.0.0/8"] - security_group_id = "${aws_security_group.web.id}" - }`, rInt) + security_group_id = "${aws_security_group.web.id}" +} + `, rInt) } const testAccAWSSecurityGroupRuleIngress_ipv6Config = ` @@ -1061,10 +1278,6 @@ resource "aws_security_group_rule" "ingress_1" { ` const testAccAWSSecurityGroupRuleIssue5310 = ` -provider "aws" { - region = "us-east-1" -} - resource "aws_security_group" "issue_5310" { name = "terraform-test-issue_5310" description = "SG for test of issue 5310" @@ -1082,50 +1295,48 @@ resource "aws_security_group_rule" "issue_5310" { func testAccAWSSecurityGroupRuleIngressClassicConfig(rInt int) string { return fmt.Sprintf(` - provider "aws" { - region = "us-east-1" - } - - resource "aws_security_group" "web" { - name = "terraform_test_%d" - description = "Used in the terraform acceptance tests" +resource "aws_security_group" "web" { + name = "terraform_test_%d" + description = "Used in the terraform acceptance tests" - tags { - Name = "tf-acc-test" - } - } + tags { + Name = "tf-acc-test" + } +} - resource "aws_security_group_rule" "ingress_1" { - type = "ingress" - protocol = "tcp" - from_port = 80 - to_port = 8000 - cidr_blocks = ["10.0.0.0/8"] +resource "aws_security_group_rule" "ingress_1" { + type = "ingress" + protocol = "tcp" + from_port = 80 + to_port = 8000 + cidr_blocks = ["10.0.0.0/8"] - security_group_id = "${aws_security_group.web.id}" - }`, rInt) + security_group_id = "${aws_security_group.web.id}" +} + `, rInt) } func testAccAWSSecurityGroupRuleEgressConfig(rInt int) string { return fmt.Sprintf(` - resource "aws_security_group" "web" { - name = "terraform_test_%d" - description = "Used in the terraform acceptance tests" +resource "aws_security_group" "web" { + name = "terraform_test_%d" + description = "Used in the terraform acceptance tests" - tags { - Name = "tf-acc-test" - } - } + tags { + Name = "tf-acc-test" + } +} - resource "aws_security_group_rule" "egress_1" { - type = "egress" - protocol = "tcp" - from_port = 80 - to_port = 8000 - cidr_blocks = ["10.0.0.0/8"] +resource "aws_security_group_rule" "egress_1" { + type = "egress" + protocol = "tcp" + from_port = 80 + to_port = 8000 + cidr_blocks = ["10.0.0.0/8"] - security_group_id = "${aws_security_group.web.id}" - }`, rInt) + security_group_id = "${aws_security_group.web.id}" +} + `, rInt) } const testAccAWSSecurityGroupRuleConfigMultiIngress = ` @@ -1164,75 +1375,75 @@ resource "aws_security_group_rule" "ingress_2" { func testAccAWSSecurityGroupRuleMultiDescription(rInt int, rType string) string { var b bytes.Buffer b.WriteString(fmt.Sprintf(` - resource "aws_vpc" "tf_sgrule_description_test" { - cidr_block = "10.0.0.0/16" - tags { - Name = "terraform-testacc-security-group-rule-multi-desc" - } - } +resource "aws_vpc" "tf_sgrule_description_test" { + cidr_block = "10.0.0.0/16" + tags { + Name = "terraform-testacc-security-group-rule-multi-desc" + } +} - resource "aws_vpc_endpoint" "s3-us-west-2" { - vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" - service_name = "com.amazonaws.us-west-2.s3" - } +resource "aws_vpc_endpoint" "s3-us-west-2" { + vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" + service_name = "com.amazonaws.us-west-2.s3" + } - resource "aws_security_group" "worker" { - name = "terraform_test_%[1]d" - vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" - description = "Used in the terraform acceptance tests" - tags { Name = "tf-sg-rule-description" } - } +resource "aws_security_group" "worker" { + name = "terraform_test_%[1]d" + vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" + description = "Used in the terraform acceptance tests" + tags { Name = "tf-sg-rule-description" } +} - resource "aws_security_group" "nat" { - name = "terraform_test_%[1]d_nat" - vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" - description = "Used in the terraform acceptance tests" - tags { Name = "tf-sg-rule-description" } - } +resource "aws_security_group" "nat" { + name = "terraform_test_%[1]d_nat" + vpc_id = "${aws_vpc.tf_sgrule_description_test.id}" + description = "Used in the terraform acceptance tests" + tags { Name = "tf-sg-rule-description" } +} - resource "aws_security_group_rule" "%[2]s_rule_1" { - security_group_id = "${aws_security_group.worker.id}" - description = "CIDR Description" - type = "%[2]s" - protocol = "tcp" - from_port = 22 - to_port = 22 - cidr_blocks = ["0.0.0.0/0"] - } +resource "aws_security_group_rule" "%[2]s_rule_1" { + security_group_id = "${aws_security_group.worker.id}" + description = "CIDR Description" + type = "%[2]s" + protocol = "tcp" + from_port = 22 + to_port = 22 + cidr_blocks = ["0.0.0.0/0"] +} - resource "aws_security_group_rule" "%[2]s_rule_2" { - security_group_id = "${aws_security_group.worker.id}" - description = "IPv6 CIDR Description" - type = "%[2]s" - protocol = "tcp" - from_port = 22 - to_port = 22 - ipv6_cidr_blocks = ["::/0"] - } +resource "aws_security_group_rule" "%[2]s_rule_2" { + security_group_id = "${aws_security_group.worker.id}" + description = "IPv6 CIDR Description" + type = "%[2]s" + protocol = "tcp" + from_port = 22 + to_port = 22 + ipv6_cidr_blocks = ["::/0"] +} - resource "aws_security_group_rule" "%[2]s_rule_3" { - security_group_id = "${aws_security_group.worker.id}" - description = "NAT SG Description" - type = "%[2]s" - protocol = "tcp" - from_port = 22 - to_port = 22 - source_security_group_id = "${aws_security_group.nat.id}" - } - `, rInt, rType)) +resource "aws_security_group_rule" "%[2]s_rule_3" { + security_group_id = "${aws_security_group.worker.id}" + description = "NAT SG Description" + type = "%[2]s" + protocol = "tcp" + from_port = 22 + to_port = 22 + source_security_group_id = "${aws_security_group.nat.id}" +} + `, rInt, rType)) if rType == "egress" { b.WriteString(fmt.Sprintf(` - resource "aws_security_group_rule" "egress_rule_4" { - security_group_id = "${aws_security_group.worker.id}" - description = "Prefix List Description" - type = "egress" - protocol = "tcp" - from_port = 22 - to_port = 22 - prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"] - } - `)) +resource "aws_security_group_rule" "egress_rule_4" { + security_group_id = "${aws_security_group.worker.id}" + description = "Prefix List Description" + type = "egress" + protocol = "tcp" + from_port = 22 + to_port = 22 + prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"] +} + `)) } return b.String() @@ -1240,10 +1451,6 @@ func testAccAWSSecurityGroupRuleMultiDescription(rInt int, rType string) string // check for GH-1985 regression const testAccAWSSecurityGroupRuleConfigSelfReference = ` -provider "aws" { - region = "us-west-2" -} - resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" tags { @@ -1271,105 +1478,107 @@ resource "aws_security_group_rule" "self" { func testAccAWSSecurityGroupRulePartialMatchingConfig(rInt int) string { return fmt.Sprintf(` - resource "aws_vpc" "default" { - cidr_block = "10.0.0.0/16" - tags { - Name = "terraform-testacc-security-group-rule-partial-match" - } - } +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + tags { + Name = "terraform-testacc-security-group-rule-partial-match" + } +} - resource "aws_security_group" "web" { - name = "tf-other-%d" - vpc_id = "${aws_vpc.default.id}" - tags { - Name = "tf-other-sg" - } - } +resource "aws_security_group" "web" { + name = "tf-other-%d" + vpc_id = "${aws_vpc.default.id}" + tags { + Name = "tf-other-sg" + } +} - resource "aws_security_group" "nat" { - name = "tf-nat-%d" - vpc_id = "${aws_vpc.default.id}" - tags { - Name = "tf-nat-sg" - } - } +resource "aws_security_group" "nat" { + name = "tf-nat-%d" + vpc_id = "${aws_vpc.default.id}" + tags { + Name = "tf-nat-sg" + } +} - resource "aws_security_group_rule" "ingress" { - type = "ingress" - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] +resource "aws_security_group_rule" "ingress" { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] - security_group_id = "${aws_security_group.web.id}" - } + security_group_id = "${aws_security_group.web.id}" +} - resource "aws_security_group_rule" "other" { - type = "ingress" - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["10.0.5.0/24"] +resource "aws_security_group_rule" "other" { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["10.0.5.0/24"] - security_group_id = "${aws_security_group.web.id}" - } + security_group_id = "${aws_security_group.web.id}" +} - // same a above, but different group, to guard against bad hashing - resource "aws_security_group_rule" "nat_ingress" { - type = "ingress" - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] +// same a above, but different group, to guard against bad hashing +resource "aws_security_group_rule" "nat_ingress" { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] - security_group_id = "${aws_security_group.nat.id}" - }`, rInt, rInt) + security_group_id = "${aws_security_group.nat.id}" +} + `, rInt, rInt) } func testAccAWSSecurityGroupRulePartialMatching_SourceConfig(rInt int) string { return fmt.Sprintf(` - resource "aws_vpc" "default" { - cidr_block = "10.0.0.0/16" - tags { - Name = "terraform-testacc-security-group-rule-partial-match" - } - } +resource "aws_vpc" "default" { + cidr_block = "10.0.0.0/16" + tags { + Name = "terraform-testacc-security-group-rule-partial-match" + } +} - resource "aws_security_group" "web" { - name = "tf-other-%d" - vpc_id = "${aws_vpc.default.id}" - tags { - Name = "tf-other-sg" - } - } +resource "aws_security_group" "web" { + name = "tf-other-%d" + vpc_id = "${aws_vpc.default.id}" + tags { + Name = "tf-other-sg" + } +} - resource "aws_security_group" "nat" { - name = "tf-nat-%d" - vpc_id = "${aws_vpc.default.id}" - tags { - Name = "tf-nat-sg" - } - } +resource "aws_security_group" "nat" { + name = "tf-nat-%d" + vpc_id = "${aws_vpc.default.id}" + tags { + Name = "tf-nat-sg" + } +} - resource "aws_security_group_rule" "source_ingress" { - type = "ingress" - from_port = 80 - to_port = 80 - protocol = "tcp" +resource "aws_security_group_rule" "source_ingress" { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" - source_security_group_id = "${aws_security_group.nat.id}" - security_group_id = "${aws_security_group.web.id}" - } + source_security_group_id = "${aws_security_group.nat.id}" + security_group_id = "${aws_security_group.web.id}" +} - resource "aws_security_group_rule" "other_ingress" { - type = "ingress" - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] +resource "aws_security_group_rule" "other_ingress" { + type = "ingress" + from_port = 80 + to_port = 80 + protocol = "tcp" + cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] - security_group_id = "${aws_security_group.web.id}" - }`, rInt, rInt) + security_group_id = "${aws_security_group.web.id}" +} + `, rInt, rInt) } const testAccAWSSecurityGroupRulePrefixListEgressConfig = ` @@ -1386,21 +1595,21 @@ resource "aws_route_table" "default" { } resource "aws_vpc_endpoint" "s3-us-west-2" { - vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}" - service_name = "com.amazonaws.us-west-2.s3" - route_table_ids = ["${aws_route_table.default.id}"] - policy = <