Skip to content

Cannot remove inline ingress or egress from aws_security_group #20046

Closed
@Nuru

Description

@Nuru

It appears this behavior has been part of aws_security_group from the start. There are bug reports about it from as far back as 2017 (now over 4 years old). If this is not going to be fixed, then please document and explain the behavior and provide a workaround.

After you provision an aws_security_group with dynamic inline ingress and egress rules, if you try to remove all of one kind of rule, the plan/apply succeeds, but none of the rules are removed.

Although this is something of a duplicate, I am opening it anyway because the bugs it duplicates are so old and this is a serious bug. I suggest leaving this open despite it being a duplicate because it has all the Terraform code and commands you need to reproduce this bug easily.

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform CLI and Terraform AWS Provider Version

Terraform v1.0.1
on darwin_amd64

  • provider registry.terraform.io/hashicorp/aws v3.47.0

Affected Resource(s)

  • aws_security_group

Terraform Configuration Files

Terraform code
variable "traffic_disabled" {
  type        = bool
  default     = false
  description = "Set true to remove all access provided by this security group"
}

locals {
  all_ingress_rules = var.traffic_disabled ? [] : [{
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }]
  all_egress_rules = var.traffic_disabled ? [] : [{
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["10.0.0.0/8"]
  }]
}

resource "aws_security_group" "default" {
  name   = "example-sg"
  vpc_id = "vpc-05d0373b3df8bde3b"
  tags   = { Name = "github-issue-example" }

  dynamic "ingress" {
    for_each = local.all_ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }

  dynamic "egress" {
    for_each = local.all_egress_rules
    content {
      from_port   = egress.value.from_port
      to_port     = egress.value.to_port
      protocol    = egress.value.protocol
      cidr_blocks = egress.value.cidr_blocks
    }
  }
}

provider "aws" {
  region = "us-west-2"
}

Expected Behavior

Removing inline ingress or egress rules should remove them from the security group

Actual Behavior

Removing all inline ingress or egress rules has no effect on the security group. (The security group is updated
as expected if at least one inline ingress and one inline egress rule remain.)

Steps to Reproduce

  • Terraform code posted above under "Terraform Configuration Files".
  • Change the vpc_id to a VPC in your account.
  • (optional) Change the region in the AWS provider to your preferred region.
  1. Initial provisioning with no inline rules: traffic_disabled = true
  • Security group is created with no ingress or egress rules
- Terraform output
$ terraform apply -lock=false -var traffic_disabled=true

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_security_group.default will be created
  + resource "aws_security_group" "default" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = (known after apply)
      + name                   = "example-sg"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Name" = "github-issue-example"
        }
      + tags_all               = {
          + "Name" = "github-issue-example"
        }
      + vpc_id                 = "vpc-05d0373b3df8bde3b"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_security_group.default: Creating...
aws_security_group.default: Creation complete after 2s [id=sg-0b7ce8ca55451342e]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  1. Add ingress and egress: traffic_disabled = false
  • Rules properly added
- Terraform output
$ terraform apply -lock=false -var traffic_disabled=false
aws_security_group.default: Refreshing state... [id=sg-0b7ce8ca55451342e]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_security_group.default will be updated in-place
  ~ resource "aws_security_group" "default" {
      ~ egress                 = [
          + {
              + cidr_blocks      = [
                  + "10.0.0.0/8",
                ]
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
        id                     = "sg-0b7ce8ca55451342e"
      ~ ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 443
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 443
            },
        ]
        name                   = "example-sg"
        tags                   = {
            "Name" = "github-issue-example"
        }
        # (6 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_security_group.default: Modifying... [id=sg-0b7ce8ca55451342e]
aws_security_group.default: Modifications complete after 1s [id=sg-0b7ce8ca55451342e]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
  1. Remove rules: traffic_disabled = true
  • No change detected, rules are not removed
- Terraform output
$ terraform apply -lock=false -var traffic_disabled=true
aws_security_group.default: Refreshing state... [id=sg-0b7ce8ca55451342e]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
  1. Destroy security group, note that rules are still in place
- Terraform output
$ terraform destroy -lock=false -var traffic_disabled=true
aws_security_group.default: Refreshing state... [id=sg-0b7ce8ca55451342e]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_security_group.default will be destroyed
  - resource "aws_security_group" "default" {
      - arn                    = "arn:aws:ec2:us-east-2:REDACTED:security-group/sg-0b7ce8ca55451342e" -> null
      - description            = "Managed by Terraform" -> null
      - egress                 = [
          - {
              - cidr_blocks      = [
                  - "10.0.0.0/8",
                ]
              - description      = ""
              - from_port        = 0
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "-1"
              - security_groups  = []
              - self             = false
              - to_port          = 0
            },
        ] -> null
      - id                     = "sg-0b7ce8ca55451342e" -> null
      - ingress                = [
          - {
              - cidr_blocks      = [
                  - "0.0.0.0/0",
                ]
              - description      = ""
              - from_port        = 443
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = []
              - self             = false
              - to_port          = 443
            },
        ] -> null
      - name                   = "example-sg" -> null
      - owner_id               = "REDACTED" -> null
      - revoke_rules_on_delete = false -> null
      - tags                   = {
          - "Name" = "github-issue-example"
        } -> null
      - tags_all               = {
          - "Name" = "github-issue-example"
        } -> null
      - vpc_id                 = "vpc-05d0373b3df8bde3b" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_security_group.default: Destroying... [id=sg-0b7ce8ca55451342e]
aws_security_group.default: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugAddresses a defect in current functionality.service/ec2Issues and PRs that pertain to the ec2 service.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions