Skip to content

google_chronicle_rule - permadiff on text field due to Chronicle API appending trailing newline #27881

Description

@shannonjones99

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 me too comments, 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.
  • If an issue is assigned to a user, that user is claiming responsibility for the issue.
  • Customers working with a Google Technical Account Manager or Customer Engineer can ask them to reach out internally to expedite investigation and resolution of this issue.

Terraform Version & Provider Version(s)

Terraform v1.9.0
on linux_amd64

  • provider registry.terraform.io/hashicorp/google v7.36.0
  • provider registry.terraform.io/hashicorp/google-beta v7.36.0

Affected Resource(s)

google_chronicle_rule

Terraform Configuration

locals {
  rule_files = fileset("${path.module}/Rules", "**/*.yaral")

  secops_rules = {
    for file_name in local.rule_files :
    trimsuffix(file_name, ".yaral") => file("${path.module}/Rules/${file_name}")
  }
}

resource "google_chronicle_rule" "rule" {
  for_each  = local.secops_rules
  project   = var.secops_project_id
  location  = var.secops_region
  instance  = var.secops_customer_id
  text      = local.secops_rules[each.key]
}

Debug Output

Unable to provide debug output at this time. Terraform is executed exclusively via GitLab CI runners and enabling TF_LOG=DEBUG in this environment poses a security risk as it would expose GCP access tokens and Vault secrets in CI logs. The phantom diff is clearly reproducible and documented via tfplan.json analysis showing the trailing \n difference between before and after states across all 1,126 managed rules.

Expected Behavior

After a terraform apply with no changes to any .yaral rule files, a subsequent terraform plan should show no changes - No changes. Infrastructure is up-to-date.

Actual Behavior

Every google_chronicle_rule resource shows a phantom update on every plan, even when no rule files have been modified. Across our environment this affects all 1,126 rules managed by Terraform.
Inspecting the tfplan.json output reveals the sole difference between before and after for each affected rule is a trailing \n on the text field:

before (read back from Chronicle API/state): rule text ends with }\n
after (from local config files): rule text ends with }

The Chronicle API is appending a trailing \n to the rule text when storing it. The provider does not normalise this when comparing state to config, causing a permanent diff on every plan.
Example diff from tfplan.json:

before: "...condition:\n    $login and $UserCount >= 3\n}\n"
after:  "...condition:\n    $login and $UserCount >= 3\n}"

Steps to reproduce

  1. Create a .yaral rule file with no trailing newline
  2. Deploy it using google_chronicle_rule via terraform apply
  3. Run terraform plan again without modifying any files
  4. Observe that the rule shows as ~ update in the plan output despite no changes
  5. Run terraform show -json on the plan and compare change.before.text vs change.after.text — the only difference is a trailing \n in before that is not present in after
  6. This affects every single google_chronicle_rule resource on every subsequent plan

Important Factoids

  • Rule files are enforced to have no trailing newline by a CI pipeline check - so the trailing \n is definitively being added by the Chronicle API on storage, not by our config
  • This was confirmed by comparing the raw bytes of local .yaral files (hexdump) against what is stored in Terraform state - the local files contain only \n Unix line endings with no trailing newline, while state always shows the trailing \n
  • Authenticated via GCP service account
  • Terraform runs on GitLab CI runners
  • Affects 1,126 rules (our entire Chronicle ruleset managed by Terraform)
  • Workaround applied: "${trimspace(file(...))}\n" — manually appending \n so what is sent matches what the API stores

References

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions