diff --git a/.changelog/37899.txt b/.changelog/37899.txt new file mode 100644 index 000000000000..27dac1871370 --- /dev/null +++ b/.changelog/37899.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_vpc_default_internet_gateway +``` \ No newline at end of file diff --git a/.github/labeler-pr-triage.yml b/.github/labeler-pr-triage.yml index b9b21a363f2c..33fbe47ccbd8 100644 --- a/.github/labeler-pr-triage.yml +++ b/.github/labeler-pr-triage.yml @@ -2170,6 +2170,7 @@ service/vpc: - changed-files: - any-glob-to-any-file: - 'internal/service/ec2/**/vpc_*' + - 'website/**/default_internet_gateway*' - 'website/**/default_network_*' - 'website/**/default_route_*' - 'website/**/default_security_*' diff --git a/internal/service/ec2/service_package_gen.go b/internal/service/ec2/service_package_gen.go index 85e72181a8c9..dae83b6c5ecb 100644 --- a/internal/service/ec2/service_package_gen.go +++ b/internal/service/ec2/service_package_gen.go @@ -488,6 +488,14 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka IdentifierAttribute: names.AttrID, }, }, + { + Factory: ResourceDefaultInternetGateway, + TypeName: "aws_default_internet_gateway", + Name: "Internet Gateway", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrID, + }, + }, { Factory: resourceDefaultNetworkACL, TypeName: "aws_default_network_acl", diff --git a/internal/service/ec2/vpc_default_internet_gateway.go b/internal/service/ec2/vpc_default_internet_gateway.go new file mode 100644 index 000000000000..7b71499ebf9d --- /dev/null +++ b/internal/service/ec2/vpc_default_internet_gateway.go @@ -0,0 +1,168 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package ec2 + +import ( + "context" + "log" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKResource("aws_default_internet_gateway", name="Internet Gateway") +// @Tags(identifierAttribute="id") +// @Testing(tagsTest=false) +func ResourceDefaultInternetGateway() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceDefaultInternetGatewayCreate, + ReadWithoutTimeout: resourceInternetGatewayRead, + UpdateWithoutTimeout: resourceInternetGatewayUpdate, + DeleteWithoutTimeout: resourceDefaultInternetGatewayDelete, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrOwnerID: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + names.AttrVPCID: { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "existing_default_internet_gateway": { + Type: schema.TypeBool, + Computed: true, + }, + names.AttrForceDestroy: { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + + CustomizeDiff: verify.SetTagsDiff, + } +} + +func resourceDefaultInternetGatewayCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + // Check if there is a default VPC + input := &ec2.DescribeVpcsInput{ + Filters: newAttributeFilterList( + map[string]string{ + "isDefault": "true", + }, + ), + } + conn := meta.(*conns.AWSClient).EC2Conn(ctx) + vpc, err := FindVPC(ctx, conn, input) + if err == nil { + log.Print("[INFO] Found existing attached EC2 Internet Gateway") + input := &ec2.DescribeInternetGatewaysInput{} + input.Filters = newAttributeFilterList(map[string]string{ + "attachment.vpc-id": *vpc.VpcId, + }) + + igw, err := FindInternetGateway(ctx, conn, input) + log.Printf("found igw with ID: %s", igw) + + if err == nil { + d.SetId(aws.StringValue(igw.InternetGatewayId)) + d.Set("existing_default_internet_gateway", true) + } else if tfresource.NotFound(err) { + log.Print("[INFO] Found default VPC without attached EC2 Internet Gateway. Creating and attaching one") + input := &ec2.CreateInternetGatewayInput{} + output, err := conn.CreateInternetGatewayWithContext(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "Creating EC2 Internet Gateway: %s", err) + } + + igw = output.InternetGateway + + d.SetId(aws.StringValue(igw.InternetGatewayId)) + d.Set("existing_default_internet_gateway", false) + + if err := attachInternetGateway(ctx, conn, d.Id(), *vpc.VpcId, d.Timeout(schema.TimeoutDelete)); err != nil { + return sdkdiag.AppendErrorf(diags, "Attaching EC2 Internet Gateway (%s): %s", d.Id(), err) + } + } else { + return sdkdiag.AppendErrorf(diags, "Creating EC2 Internet Gateway (%s): %s", d.Id(), err) + } + } + return append(diags, resourceInternetGatewayRead(ctx, d, meta)...) +} + +func resourceDefaultInternetGatewayDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + if d.Get(names.AttrForceDestroy).(bool) { + // See if the VPC assigned to the IGW has the isDefault property + conn := meta.(*conns.AWSClient).EC2Conn(ctx) + input := &ec2.DescribeVpcsInput{ + Filters: newAttributeFilterList( + map[string]string{ + "isDefault": "true", + "vpc-id": d.Get(names.AttrVPCID).(string), + }, + ), + } + _, err := FindVPC(ctx, conn, input) + + if err == nil { + // Detach if it is attached. + if v, ok := d.GetOk(names.AttrVPCID); ok { + if err := detachInternetGateway(ctx, conn, d.Id(), v.(string), d.Timeout(schema.TimeoutDelete)); err != nil { + return sdkdiag.AppendErrorf(diags, "deleting EC2 Internet Gateway (%s): %s", d.Id(), err) + } + + input := &ec2.DeleteInternetGatewayInput{ + InternetGatewayId: aws.String(d.Id()), + } + + log.Printf("[INFO] Deleting Internet Gateway: %s", d.Id()) + _, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, d.Timeout(schema.TimeoutDelete), func() (interface{}, error) { + return conn.DeleteInternetGatewayWithContext(ctx, input) + }, errCodeDependencyViolation) + + if tfawserr.ErrCodeEquals(err, errCodeInvalidInternetGatewayIDNotFound) { + return diags + } + + if err != nil { + return sdkdiag.AppendErrorf(diags, "deleting EC2 Internet Gateway (%s): %s", d.Id(), err) + } + } + } + } + log.Printf("[INFO] Skipping Internet Gateway: %s", d.Id()) + return diags +} diff --git a/internal/service/ec2/vpc_default_internet_gateway_test.go b/internal/service/ec2/vpc_default_internet_gateway_test.go new file mode 100644 index 000000000000..d5f0c48f32fd --- /dev/null +++ b/internal/service/ec2/vpc_default_internet_gateway_test.go @@ -0,0 +1,288 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package ec2_test + +import ( + "context" + "fmt" + "testing" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go/service/ec2" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfec2 "github.com/hashicorp/terraform-provider-aws/internal/service/ec2" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccVPCDefaultInternetGateway_basic(t *testing.T) { + ctx := acctest.Context(t) + var v ec2.InternetGateway + resourceName := "aws_default_internet_gateway.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDefaultInternetGatewayDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccVPCDefaultInternetGatewayConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "ec2", regexache.MustCompile(`internet-gateway/igw-.+`)), + acctest.CheckResourceAttrAccountID(resourceName, names.AttrOwnerID), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, names.AttrVPCID, ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccVPCDefaultInternetGateway_disappears(t *testing.T) { + ctx := acctest.Context(t) + var v ec2.InternetGateway + resourceName := "aws_default_internet_gateway.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDefaultInternetGatewayDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccVPCDefaultInternetGatewayConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfec2.ResourceInternetGateway(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccVPCDefaultInternetGateway_Attachment(t *testing.T) { + ctx := acctest.Context(t) + var v ec2.InternetGateway + resourceName := "aws_default_internet_gateway.test" + vpc1ResourceName := "aws_vpc.test1" + vpc2ResourceName := "aws_vpc.test2" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDefaultInternetGatewayDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccVPCDefaultInternetGatewayConfig_attachment(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, names.AttrVPCID, vpc1ResourceName, names.AttrID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccVPCDefaultInternetGatewayConfig_attachmentUpdated(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, names.AttrVPCID, vpc2ResourceName, names.AttrID), + ), + }, + }, + }) +} + +func TestAccVPCDefaultInternetGateway_Tags(t *testing.T) { + ctx := acctest.Context(t) + var v ec2.InternetGateway + resourceName := "aws_default_internet_gateway.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDefaultInternetGatewayDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccVPCDefaultInternetGatewayConfig_tags1(rName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccVPCDefaultInternetGatewayConfig_tags2(rName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct2), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccVPCDefaultInternetGatewayConfig_tags1(rName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckDefaultInternetGatewayExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} + +func testAccCheckDefaultInternetGatewayDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_default_internet_gateway" { + continue + } + + _, err := tfec2.FindInternetGatewayByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("EC2 Internet Gateway %s still exists", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckDefaultInternetGatewayExists(ctx context.Context, n string, v *ec2.InternetGateway) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No EC2 Internet Gateway ID is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn(ctx) + + output, err := tfec2.FindInternetGatewayByID(ctx, conn, rs.Primary.ID) + if err != nil { + return err + } + + *v = *output + + return nil + } +} + +const testAccVPCDefaultInternetGatewayConfig_basic = ` +resource "aws_default_internet_gateway" "test" {} +` + +func testAccVPCDefaultInternetGatewayConfig_attachment(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test1" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = "%[1]s-1" + } +} + +resource "aws_vpc" "test2" { + cidr_block = "10.2.0.0/16" + + tags = { + Name = "%[1]s-2" + } +} + +resource "aws_default_internet_gateway" "test" { + vpc_id = aws_vpc.test1.id + + tags = { + Name = %[1]q + } +} +`, rName) +} + +func testAccVPCDefaultInternetGatewayConfig_attachmentUpdated(rName string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test1" { + cidr_block = "10.1.0.0/16" + + tags = { + Name = "%[1]s-1" + } +} + +resource "aws_vpc" "test2" { + cidr_block = "10.2.0.0/16" + + tags = { + Name = "%[1]s-2" + } +} + +resource "aws_default_internet_gateway" "test" { + vpc_id = aws_vpc.test2.id + + tags = { + Name = %[1]q + } +} +`, rName) +} + +func testAccVPCDefaultInternetGatewayConfig_tags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_default_internet_gateway" "test" { + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccVPCDefaultInternetGatewayConfig_tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_default_internet_gateway" "test" { + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/names/data/names_data.csv b/names/data/names_data.csv index 4944a0efc6d7..0fe2e255e86e 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -374,7 +374,7 @@ transfer,transfer,transfer,transfer,,transfer,,,Transfer,Transfer,,,2,,aws_trans translate,translate,translate,translate,,translate,,,Translate,Translate,,1,,,aws_translate_,,translate_,Translate,Amazon,,x,,,,,Translate,,,, ,,,,,,,,,,,,,,,,,Trusted Advisor,AWS,x,,,,,,,,,,Part of Support ,,,,,verifiedaccess,ec2,,VerifiedAccess,,,,,aws_verifiedaccess,aws_verifiedaccess_,verifiedaccess_,verifiedaccess_,Verified Access,AWS,x,,,x,,,,,,,Part of EC2 -,,,,,vpc,ec2,,VPC,,,,,aws_((default_)?(network_acl|route_table|security_group|subnet|vpc(?!_ipam))|ec2_(managed|network|subnet|traffic)|egress_only_internet|flow_log|internet_gateway|main_route_table_association|nat_gateway|network_interface|prefix_list|route\b),aws_vpc_,vpc_,default_network_;default_route_;default_security_;default_subnet;default_vpc;ec2_managed_;ec2_network_;ec2_subnet_;ec2_traffic_;egress_only_;flow_log;internet_gateway;main_route_;nat_;network_;prefix_list;route_;route\.;security_group;subnet;vpc_dhcp_;vpc_endpoint;vpc_ipv;vpc_network_performance;vpc_peering_;vpc_security_group_;vpc\.;vpcs\.,VPC (Virtual Private Cloud),Amazon,x,,,x,,,,,,,Part of EC2 +,,,,,vpc,ec2,,VPC,,,,,aws_((default_)?(network_acl|route_table|security_group|subnet|vpc(?!_ipam))|ec2_(managed|network|subnet|traffic)|egress_only_internet|flow_log|internet_gateway|main_route_table_association|nat_gateway|network_interface|prefix_list|route\b),aws_vpc_,vpc_,default_internet_gateway;default_network_;default_route_;default_security_;default_subnet;default_vpc;ec2_managed_;ec2_network_;ec2_subnet_;ec2_traffic_;egress_only_;flow_log;internet_gateway;main_route_;nat_;network_;prefix_list;route_;route\.;security_group;subnet;vpc_dhcp_;vpc_endpoint;vpc_ipv;vpc_network_performance;vpc_peering_;vpc_security_group_;vpc\.;vpcs\.,VPC (Virtual Private Cloud),Amazon,x,,,x,,,,,,,Part of EC2 vpc-lattice,vpclattice,vpclattice,vpclattice,,vpclattice,,,VPCLattice,VPCLattice,,,2,,aws_vpclattice_,,vpclattice_,VPC Lattice,Amazon,,,,,,,VPC Lattice,ListServices,,, ,,,,,ipam,ec2,,IPAM,,,,,aws_vpc_ipam,aws_ipam_,ipam_,vpc_ipam,VPC IPAM (IP Address Manager),Amazon,x,,,x,,,,,,,Part of EC2 ,,,,,vpnclient,ec2,,ClientVPN,,,,,aws_ec2_client_vpn,aws_vpnclient_,vpnclient_,ec2_client_vpn_,VPN (Client),AWS,x,,,x,,,,,,,Part of EC2 diff --git a/website/docs/r/default_internet_gateway.html.markdown b/website/docs/r/default_internet_gateway.html.markdown new file mode 100644 index 000000000000..da31571f9d16 --- /dev/null +++ b/website/docs/r/default_internet_gateway.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "VPC (Virtual Private Cloud)" +layout: "aws" +page_title: "AWS: aws_default_internet_gateway" +description: |- + Manage a default internet gateway resource. +--- + +# Resource: aws_default_internet_gateway + +Provides a resource to manage the [internet gateway](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/default-vpc.html#default-vpc-basics) attached to the default VPC in the current region. + +**This is an advanced resource** and has special caveats to be aware of when using it. Please read this document in its entirety before using this resource. + +Please be aware that there is no such thing as "default Internet Gateway" on AWS. When creating a default VPC, it will automatically create an Internet Gateway and attach it to the default VPC. The new IGW has no properties that is specific for being part of the default VPC's infrastructure. The aws_default_internet_gateway resource assumes that the Internet Gateway attached to the default VPC is the "default Internet Gateway". + +The `aws_default_internet_gateway` resource behaves differently from normal resources in that, if an Internet Gateway exists and attached to the default VPC, Terraform does not _create_ this resource, but instead "adopts" it into management. +If no Internet Gateway exists that is attached to the default VPC, Terraform creates a new internet gateway and attaches to the default VPC. +By default, `terraform destroy` does not delete the internet gateway, but does remove the resource from Terraform state. +Set the `force_destroy` argument to `true` to delete the "default" Internet Gateway". + +## Example Usage + +```terraform +resource "aws_default_internet_gateway" "default" { + force_destroy = true + depends_on = [aws_default_vpc.default] +} +``` + +## Argument Reference + +This resource supports the following additional arguments: + +* `force_destroy` - (Optional) Whether destroying the resource deletes the Internet Gateway attached to the default VPC. Default: `false` + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `id` - The ID of the Internet Gateway. +* `arn` - The ARN of the Internet Gateway. +* `owner_id` - The ID of the AWS account that owns the internet gateway. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Internet Gateways using the `id`. For example: + +```terraform +import { + to = aws_default_internet_gateway.gw + id = "igw-c0a643a9" +} +``` + +Using `terraform import`, import default Internet Gateways using the `id`. For example: + +```console +% terraform import aws_default_internet_gateway.gw igw-c0a643a9 +```