Lb-internal Now Requiring source_tags

Useful links

Issue I’m Not Understanding

In the terraform-google lb-internal a required input of source_tags is needed for a resource created:


after upgrading the lb-internal to version 5 (the change was actually in 4) I received a gitlab pipeline since I had been defining:

source_tags      = null

relying on the VPC Firewall rule documentation:

If all source IP ranges, source tags, and source service accounts are omitted, Google Cloud defines the source as any IPv4 address ( IPv6 sources are not included.

Now the lb module requires source_tags to be defined so this default strategy no longer works.

However, requiring only source_tags doesn’t seem to make sense to me. In the google_compute_firewall documentation we see all three: source_ranges, source_tags and source_service_accounts are optional, except when the rule is for INGRESS traffic then one is required. Reading through each parameter my understanding is:

  • source_service_accounts - can’t be used with target or source tags
  • source_ranges and source_tags - can both be defined

and the documentation states:

If both properties are set, the firewall will apply to traffic that has source IP address within sourceRanges OR the source IP that belongs to a tag listed in the sourceTags property

I think the relevant documentation that applies to the default-ilb-fw resource is:

When combinations are used, the effective source set is the union of the source range IP addresses and the instances identified by network tags or service accounts. That is, if either the source IP range, or the source tags (or source service accounts) match the filter criteria, the source is included in the effective source set.

The key being a union where if I was to define the optional source_ip_ranges = in the lb-internal module and an arbitrary source_tags = <some_tag> traffic should be in the CIDR set and work. Is that correct? I don’t want a source tag at all for the “Filter” section in the VPC Firewall rules, I’d prefer only: IP ranges: as it had always been.

I found the PR, which is linked above, and the Go code change, where the function is:

func resourceComputeFirewallSourceFieldsCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v interface{}) error {
	direction := diff.Get("direction").(string)

	if direction != "EGRESS" {
		_, tagsOk := diff.GetOk("source_tags")
		_, rangesOk := diff.GetOk("source_ranges")
		_, sasOk := diff.GetOk("source_service_accounts")

		_, tagsExist := diff.GetOkExists("source_tags")
		// ranges is computed, but this is what we're trying to avoid, so we're not going to check this
		_, sasExist := diff.GetOkExists("source_service_accounts")

		if !tagsOk && !rangesOk && !sasOk && !tagsExist && !sasExist {
			return fmt.Errorf("one of source_tags, source_ranges, or source_service_accounts must be defined")

	return nil

My main question is why is it that source tags is the required parameter and not the more obvious source_ranges || source_tags being required?