Skip to content

fix(compute): omit enforceOnKey when enforceOnKeyConfigs is set in Co… - #12775

Merged
maqiuyujoyce merged 1 commit into
GoogleCloudPlatform:masterfrom
eugenenuke:fix-computesecuritypolicy-enforceonkey
Oct 10, 2026
Merged

maqiuyujoyce merged 1 commit into
GoogleCloudPlatform:masterfrom
eugenenuke:fix-computesecuritypolicy-enforceonkey

Conversation

@eugenenuke

@eugenenuke eugenenuke commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

BRIEF Change description

Summary

Configuring rateLimitOptions.enforceOnKeyConfigs on a ComputeSecurityPolicy rule previously failed with a GCP API error (Only one of enforceOnKey and enforceOnKeyConfigs can be specified) because the Terraform schema for rate_limit_options.enforce_on_key defined Default: "ALL". Even when enforceOnKey was omitted in YAML, "ALL" was injected alongside enforceOnKeyConfigs.

Alignment with Upstream & Config Connector Adaptations

This change incorporates the approach from upstream terraform-provider-google-beta and adapts it for Config Connector's continuous reconciliation model (state-into-spec: absent):

  1. Upstream Alignment:
    • Removed Default: "ALL" from enforce_on_key so enforce_on_key_configs can be specified without conflict.
    • Retained unconditional ForceSendFields: []string{"EnforceOnKey", "EnforceOnKeyName", "EnforceOnKeyConfigs"} in expandSecurityPolicyRuleRateLimitOptions so in-place rule updates (patchRule) clear previously configured mutually exclusive fields on GCP.
  2. Preventing state-into-spec: absent Permadiffs:
    • Removing Default: "ALL" alone causes a permadiff when both enforceOnKey and enforceOnKeyConfigs are omitted: KCC's spec remains "" while GCP returns "ALL", causing schema.TypeSet hash mismatches and infinite patchRule loops.
    • Added Computed: true to enforce_on_key.
    • Defaulted enforceOnKey = "ALL" in expandSecurityPolicyRuleRateLimitOptions only when both enforceOnKey and enforceOnKeyConfigs are empty.
    • Added resourceComputeSecurityPolicyRuleHash and effectiveEnforceOnKey to normalize omitted enforce_on_key ("") to "ALL" during TypeSet hashing and updateMask diffing when enforce_on_key_configs is empty.

Risk Mitigation & Testing

  • Minimal Diff: Used a sync.Once-cached helper (getComputeSecurityPolicyRuleElem) to reference the rule schema in the custom hash function without relocating the ~330-line inline schema definition. Zero existing test fixtures were modified.
  • Unit Tests: Added unit tests in resource_compute_security_policy_internal_test.go verifying payload expansion and TypeSet hash equivalence when enforce_on_key is omitted vs. explicitly set to "ALL".
  • E2E & Real GCP Verification: Added the computesecuritypolicy-ratelimit E2E fixture testing enforceOnKeyConfigs, enforceOnKey, rule transitions, and omitted defaults. Validated against real GCP via ./hack/record-gcp and updated mockgcp so that mock and real GCP HTTP traces match byte-for-byte.

Fixes #1022 (b/556657009)

WHY do we need this change?

To allow ComputeSecurityPolicy rules to configure enforceOnKeyConfigs without requiring users to supply the awkward workaround enforceOnKey: "".

Additionally, exporting a security policy created via the GCP Console with config-connector export omits enforceOnKey, causing subsequent kubectl apply operations of exported manifests to fail with HTTP 400 unless manually edited.

Special notes for your reviewer:

None.

Does this PR add something which needs to be 'release noted'?

Fixed an issue in `ComputeSecurityPolicy` where setting `rateLimitOptions.enforceOnKeyConfigs` failed with an API error unless `enforceOnKey: ""` was explicitly specified.
  • Reviewer reviewed release note.

Intended Milestone

1.158.0

  • Reviewer tagged PR with the actual milestone.

Tests you have done

  • Run make ready-pr to ensure this PR is ready for review.
  • Perform necessary E2E testing for changed resources.

@eugenenuke
eugenenuke force-pushed the fix-computesecuritypolicy-enforceonkey branch from c80433f to 8ba07a9 Compare September 16, 2026 19:37
@eugenenuke

Copy link
Copy Markdown
Member Author

/cc @acpana

can you take a look please?

@google-oss-prow
google-oss-prow Bot requested a review from acpana September 16, 2026 20:23
@eugenenuke
eugenenuke force-pushed the fix-computesecuritypolicy-enforceonkey branch 2 times, most recently from 580a803 to f1a4c5e Compare September 17, 2026 08:45

@maqiuyujoyce maqiuyujoyce left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please remove ComputeSecurityPolicy from tests/e2e/ratcheting.go:223 and rerun the real GCP tests?

A primary motivation for adding the custom TypeSet hasher and defaulting logic is to prevent permadiffs and reconciliation loops. Because ComputeSecurityPolicy is currently exempted in ratcheting.go, the integration tests actually skips the re-reconciliation step, which won't help validate if permdiff is gone.

return computeSecurityPolicyRuleElem
}

func effectiveEnforceOnKey(rloMap map[string]interface{}) string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: A more consistent function name would probably be canonicalizeEnforceOnKey or setDefaultEnforceOnKey.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Renamed to canonicalizeEnforceOnKey.

rateLimitThreshold:
count: 100
intervalSec: 60
enforceOnKey: IP

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make sure we are on the same page: Because spec.rule is an atomic list treated as the full Source of Truth, omitting enforceOnKeyConfigs here naturally clears it on GCP rather than leaving it unmanaged. This is different from a typical field not under a list.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, enforceOnKey/enforceOnKeyConfigs cannot be used together anyway, and this behaviour (clearing) is visible in the recorded logs:

  • In _http_old_controller.log (lines 265–293), patchRule sends updateMask=rate_limit_options.enforce_on_key,rate_limit_options.enforce_on_key_configs with "enforceOnKey": "IP" and "enforceOnKeyConfigs": [], and the subsequent GET (lines 477–487) confirms enforceOnKeyConfigs is cleared on GCP.
  • In _http.log (lines 248–291 & 414–423), the Direct controller's PATCH replaces rules and similarly clears enforceOnKeyConfigs on GCP.

@eugenenuke
eugenenuke force-pushed the fix-computesecuritypolicy-enforceonkey branch from f1a4c5e to 34b6eae Compare October 9, 2026 13:11
@eugenenuke

Copy link
Copy Markdown
Member Author

Done. Removed ComputeSecurityPolicy from tests/e2e/ratcheting.go and reran the real GCP and mock E2E tests.

Removing the exemption also revealed a similar permadiff on rules in the Direct controller. I updated assignGCPDefaults there as well so all ComputeSecurityPolicy fixtures pass re-reconciliation across both controllers.

@maqiuyujoyce maqiuyujoyce left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@maqiuyujoyce
maqiuyujoyce added this pull request to the merge queue Oct 10, 2026
@google-oss-prow google-oss-prow Bot added the lgtm label Oct 10, 2026
@google-oss-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: maqiuyujoyce

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Merged via the queue into GoogleCloudPlatform:master with commit fce16bc Oct 10, 2026
254 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloud Armor - Config Connector gives Invalid value for field 'resource.rateLimitOptions.enforceOnKeyConfigs'

2 participants