Skip to content

Commit 8b70bef

Browse files
authored
Merge pull request #26697 from hashicorp/b-sg-no-vpc
resource/aws_security_group: Use default VPC when no VPC ID passed
2 parents 4bc6a94 + 1b2481a commit 8b70bef

File tree

4 files changed

+75
-12
lines changed

4 files changed

+75
-12
lines changed

.changelog/26697.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
resource/aws_security_group: Defaults to default VPC when not supplied
3+
```

internal/service/ec2/vpc_security_group.go

+2-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package ec2
33
import (
44
"bytes"
55
"context"
6-
"errors"
76
"fmt"
87
"log"
98
"regexp"
@@ -181,10 +180,6 @@ func resourceSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error
181180
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
182181
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))
183182

184-
if _, ok := d.GetOk("vpc_id"); !ok {
185-
return errors.New(`with the retirement of EC2-Classic no new Security Groups can be created without referencing a VPC`)
186-
}
187-
188183
name := create.Name(d.Get("name").(string), d.Get("name_prefix").(string))
189184
input := &ec2.CreateSecurityGroupInput{
190185
GroupName: aws.String(name),
@@ -202,7 +197,6 @@ func resourceSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error
202197
input.TagSpecifications = tagSpecificationsFromKeyValueTags(tags, ec2.ResourceTypeSecurityGroup)
203198
}
204199

205-
log.Printf("[DEBUG] Creating Security Group: %s", input)
206200
output, err := conn.CreateSecurityGroup(input)
207201

208202
if err != nil {
@@ -220,6 +214,7 @@ func resourceSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error
220214

221215
// AWS defaults all Security Groups to have an ALLOW ALL egress rule.
222216
// Here we revoke that rule, so users don't unknowingly have/use it.
217+
// This will only be false for Security Groups in EC2-Classic
223218
if aws.StringValue(group.VpcId) != "" {
224219
input := &ec2.RevokeSecurityGroupEgressInput{
225220
GroupId: aws.String(d.Id()),
@@ -348,6 +343,7 @@ func resourceSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error
348343
return fmt.Errorf("updating Security Group (%s) %s rules: %w", d.Id(), securityGroupRuleTypeIngress, err)
349344
}
350345

346+
// This will only be false for Security Groups in EC2-Classic
351347
if d.Get("vpc_id") != nil {
352348
err = updateSecurityGroupRules(conn, d, securityGroupRuleTypeEgress, group)
353349

internal/service/ec2/vpc_security_group_test.go

+68-5
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ func TestAccVPCSecurityGroup_basic(t *testing.T) {
502502
acctest.CheckResourceAttrAccountID(resourceName, "owner_id"),
503503
resource.TestCheckResourceAttr(resourceName, "revoke_rules_on_delete", "false"),
504504
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
505-
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
505+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"),
506506
),
507507
},
508508
{
@@ -538,6 +538,42 @@ func TestAccVPCSecurityGroup_disappears(t *testing.T) {
538538
})
539539
}
540540

541+
func TestAccVPCSecurityGroup_noVPC(t *testing.T) {
542+
var group ec2.SecurityGroup
543+
resourceName := "aws_security_group.test"
544+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
545+
546+
resource.ParallelTest(t, resource.TestCase{
547+
PreCheck: func() { acctest.PreCheck(t) },
548+
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
549+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
550+
CheckDestroy: testAccCheckSecurityGroupDestroy,
551+
Steps: []resource.TestStep{
552+
{
553+
Config: testAccVPCSecurityGroupConfig_noVPC(rName),
554+
Check: resource.ComposeAggregateTestCheckFunc(
555+
testAccCheckSecurityGroupExists(resourceName, &group),
556+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "data.aws_vpc.default", "id"),
557+
),
558+
},
559+
{
560+
ResourceName: resourceName,
561+
ImportState: true,
562+
ImportStateVerify: true,
563+
ImportStateVerifyIgnore: []string{"revoke_rules_on_delete"},
564+
},
565+
{
566+
Config: testAccVPCSecurityGroupConfig_defaultVPC(rName),
567+
PlanOnly: true,
568+
},
569+
{
570+
Config: testAccVPCSecurityGroupConfig_noVPC(rName),
571+
PlanOnly: true,
572+
},
573+
},
574+
})
575+
}
576+
541577
func TestAccVPCSecurityGroup_nameGenerated(t *testing.T) {
542578
var group ec2.SecurityGroup
543579
resourceName := "aws_security_group.test"
@@ -1339,7 +1375,7 @@ func TestAccVPCSecurityGroup_vpc(t *testing.T) {
13391375
"cidr_blocks.#": "1",
13401376
"cidr_blocks.0": "10.0.0.0/8",
13411377
}),
1342-
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
1378+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"),
13431379
),
13441380
},
13451381
{
@@ -1375,7 +1411,7 @@ func TestAccVPCSecurityGroup_vpcNegOneIngress(t *testing.T) {
13751411
"cidr_blocks.#": "1",
13761412
"cidr_blocks.0": "10.0.0.0/8",
13771413
}),
1378-
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
1414+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"),
13791415
),
13801416
},
13811417
{
@@ -1411,7 +1447,7 @@ func TestAccVPCSecurityGroup_vpcProtoNumIngress(t *testing.T) {
14111447
"cidr_blocks.#": "1",
14121448
"cidr_blocks.0": "10.0.0.0/8",
14131449
}),
1414-
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
1450+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"),
14151451
),
14161452
},
14171453
{
@@ -2198,7 +2234,7 @@ func TestAccVPCSecurityGroup_emrDependencyViolation(t *testing.T) {
21982234
acctest.CheckResourceAttrAccountID(resourceName, "owner_id"),
21992235
resource.TestCheckResourceAttr(resourceName, "revoke_rules_on_delete", "true"),
22002236
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
2201-
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
2237+
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"),
22022238
),
22032239
ExpectError: regexp.MustCompile("unexpected state"),
22042240
},
@@ -2453,6 +2489,33 @@ resource "aws_security_group" "test" {
24532489
`, rName, namePrefix)
24542490
}
24552491

2492+
func testAccVPCSecurityGroupConfig_noVPC(rName string) string {
2493+
return fmt.Sprintf(`
2494+
resource "aws_security_group" "test" {
2495+
name = %[1]q
2496+
}
2497+
2498+
data "aws_vpc" "default" {
2499+
default = true
2500+
}
2501+
2502+
`, rName)
2503+
}
2504+
2505+
func testAccVPCSecurityGroupConfig_defaultVPC(rName string) string {
2506+
return fmt.Sprintf(`
2507+
resource "aws_security_group" "test" {
2508+
name = %[1]q
2509+
vpc_id = data.aws_vpc.default.id
2510+
}
2511+
2512+
data "aws_vpc" "default" {
2513+
default = true
2514+
}
2515+
2516+
`, rName)
2517+
}
2518+
24562519
func testAccVPCSecurityGroupConfig_tags1(rName, tagKey1, tagValue1 string) string {
24572520
return fmt.Sprintf(`
24582521
resource "aws_vpc" "test" {

website/docs/r/security_group.html.markdown

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,15 @@ resource "aws_security_group" "sg_with_changeable_name" {
118118

119119
The following arguments are supported:
120120

121-
* `description` - (Optional, Forces new resource) Security group description. Defaults to `Managed by Terraform`. Cannot be `""`. __NOTE__: This field maps to the AWS `GroupDescription` attribute, for which there is no Update API. If you'd like to classify your security groups in a way that can be updated, use `tags`.
121+
* `description` - (Optional, Forces new resource) Security group description. Defaults to `Managed by Terraform`. Cannot be `""`. **NOTE**: This field maps to the AWS `GroupDescription` attribute, for which there is no Update API. If you'd like to classify your security groups in a way that can be updated, use `tags`.
122122
* `egress` - (Optional, VPC only) Configuration block for egress rules. Can be specified multiple times for each egress rule. Each egress block supports fields documented below. This argument is processed in [attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html).
123123
* `ingress` - (Optional) Configuration block for ingress rules. Can be specified multiple times for each ingress rule. Each ingress block supports fields documented below. This argument is processed in [attribute-as-blocks mode](https://www.terraform.io/docs/configuration/attr-as-blocks.html).
124124
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
125125
* `name` - (Optional, Forces new resource) Name of the security group. If omitted, Terraform will assign a random, unique name.
126126
* `revoke_rules_on_delete` - (Optional) Instruct Terraform to revoke all of the Security Groups attached ingress and egress rules before deleting the rule itself. This is normally not needed, however certain AWS services such as Elastic Map Reduce may automatically add required rules to security groups used with the service, and those rules may contain a cyclic dependency that prevent the security groups from being destroyed without removing the dependency first. Default `false`.
127127
* `tags` - (Optional) Map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.
128128
* `vpc_id` - (Optional, Forces new resource) VPC ID.
129+
Defaults to the region's default VPC.
129130

130131
### ingress
131132

0 commit comments

Comments
 (0)