Conceptual principles and Provider validation logic

My goal is to understand reasoning, or learning about conceptual principles, around what should and should not be encoded as part of a Terraform Provider.

Consider the following configuration:

resource "aws_security_group" "this" {}

resource "aws_security_group_rule" "a" {
  security_group_id = aws_security_group.this.id
  type              = "egress"
  protocol          = "all"
  from_port         = -1
  to_port           = -1
  cidr_blocks = [
    "5.5.5.5/32",
  ]
}

resource "aws_security_group_rule" "b" {
  security_group_id = aws_security_group.this.id
  type              = "egress"
  protocol          = "all"
  from_port         = -1
  to_port           = -1
  cidr_blocks       = [
    "1.1.1.1/32",
    "2.2.2.2/32",
    "3.3.3.3/32",
    "4.4.4.4/32",
    # "5.5.5.5/32",
  ]
}

The AWS EC2 API for managing Security Group Rules (SGR) does not allow update-in-place, and instead requires replacement. If the above configuration has already been Applied, and 5.5.5.5/32 was uncommented and preparing to Apply, Terraform would do the following actions:

  1. Destroy aws_security_group.b
  2. Create aws_security_group.b with the new CIDR included (will fail)

Step 2 will fail since a duplicate SGR (aws_security_group_rule.a) exists covering 5.5.5.5/32. This means all the other CIDRs (1.1.1.1/32, etc.) have been removed and have not been restored all because of one overlap.

I am aware the aws_vpc_security_group_egress_rule-styled resources exist, which help address this, in part by only allowing one cidr_ipv4/cidr_ipv6 at a time, but please entertain my broader question.

Why shouldn’t the AWS Provider change to perform the following actions:

  1. Inspect incoming source code configuration, checking for each CIDR block that there is no other SGR already attached, and that there is no other pending resource creation which also creates an overlapping CIDR
  2. Destroy aws_security_group.b
  3. Create aws_security_group.b with the new CIDR included

Is it because:

  • Terraform ought to follow a simple declarative model, doing what source code provides and no more, no less.
  • Accounting for all the various conditions a remote API may impose is too encumbering for which to encode logic.
  • A separate reason.

I’d appreciate understanding the broad principles for designing what a Provider should do and what it shouldn’t. Thanks for your consideration!