Skip to content

Add plan-time YARA-L verification for chronicle_rule - #22

Closed
b3ngriffiths wants to merge 3 commits into
form3tech-oss:masterfrom
b3ngriffiths:claude/yara-rule-plan-verification-h7kqhx
Closed

Add plan-time YARA-L verification for chronicle_rule#22
b3ngriffiths wants to merge 3 commits into
form3tech-oss:masterfrom
b3ngriffiths:claude/yara-rule-plan-verification-h7kqhx

Conversation

@b3ngriffiths

Copy link
Copy Markdown
Contributor

What

Adds a CustomizeDiff hook to chronicle_rule so invalid YARA-L 2.0 in rule_text fails during terraform plan instead of only at terraform apply.

Previously client.VerifyYARARule was only called in Create/Update, so a broken rule surfaced late (during apply). This wires the same verification into plan.

How

resourceRuleCustomizeDiff calls the existing client.VerifyYARARule (no duplicated HTTP logic) and only when it's relevant:

  • Verifies when rule_text is set on a new resource, or changes on an existing one.
  • Skips when only live_enabled / alerting_enabled change (no API call).
  • Skips when rule_text is empty or unknown/computed at plan time (e.g. interpolated from another resource) — falling back to the apply-time guard, since CustomizeDiff can't reliably validate values that aren't concrete yet.
  • On failure returns error verifying YARA-L 2.0 rule during plan: <Chronicle context>, surfacing the compiler error in the plan output. The during plan wording distinguishes it from the apply-time message.

The existing Create/Update verification is left in place as a defence-in-depth apply-time guard. Destroy plans are unaffected (the SDK returns before CustomizeDiff for a null proposed state).

Tests

New unit tests in chronicle/resource_rule_customizediff_test.go — no live Chronicle credentials required. They drive a real *chronicle.Client against an httptest.Server via WithRuleBasePath (the same mechanism the provider uses for rule_custom_endpoint), so VerifyYARARule exercises real request/response handling:

  • verifies on new resource and on rule_text change
  • fails the plan on an invalid rule, surfacing Chronicle's compilation context
  • does not call verifyRule when only live_enabled / alerting_enabled change, or when rule_text is unknown
  • treats a response that omits success as invalid, and fails the plan on an API error
  • Create/Update still verify before mutating Chronicle

Run:

  • make test — pass (acceptance tests skipped without TF_ACC)
  • go test -race ./chronicle/... — pass, no data races
  • make lint (gofmt + go vet) — clean

Caveat

terraform plan now makes an authenticated verifyRule API call to Chronicle whenever rule_text is set or changed. Plan therefore requires valid Backstory API credentials and network access, and consumes the VerifyYARARule rate limiter. verifyRule is validation-only — it does not create or evaluate rules.

Docs

No schema attributes/descriptions changed, so docs/resources/rule.md needs no update.

Add a CustomizeDiff hook to chronicle_rule that calls the existing
client.VerifyYARARule against Chronicle's compiler whenever rule_text
is changing and its planned value is a known, non-empty string. This
makes invalid YARA-L 2.0 fail during "terraform plan" instead of only
"terraform apply", while leaving unrelated changes (live_enabled,
alerting_enabled) and unknown/computed rule_text values alone. The
existing apply-time verification in Create/Update is left in place as
a defence-in-depth guard.

Add unit tests covering: verification on new/changed rule_text, plan
failure with Chronicle's compilation context surfaced, skipping when
rule_text is unchanged/unknown, a response that omits "success", API
errors during plan, and that Create/Update still verify before
mutating Chronicle. Tests use an httptest server wired up via the same
WithRuleBasePath mechanism the provider uses for rule_custom_endpoint,
so no live Chronicle credentials are required.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kLA4K5wvUAdWG2epAVseV
Make the CustomizeDiff handling of unknown planned values explicit:
replace the GetOk-based skip with diff.NewValueKnown("rule_text") and
read the new planned value via diff.GetChange, which is the clearer,
self-documenting SDKv2 API for "only validate this if the new value is
known". Behaviour for concrete strings, and the apply-time verification
in Create/Update, are unchanged.

Add a focused test for the update-from-known-to-unknown path, where
HasChange is true but the new value is unknown -- the case where
NewValueKnown is load-bearing (the existing create-with-unknown test is
short-circuited by HasChange first).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kLA4K5wvUAdWG2epAVseV
…ication

CustomizeDiff can be invoked with a nil meta when the provider
configuration itself is not yet known at plan time (e.g. credentials
interpolated from another resource). The unconditional
meta.(*chronicle.Client) type assertion then panicked; skip plan-time
verification in that case and fall back to the apply-time check in
Create/Update. Add a regression test that panics without the guard.

Document the behaviour change in the chronicle_rule docs (template and
generated page): plans that create a rule or change rule_text now make
an authenticated verifyRule call, so they need Backstory credentials
and network access to Chronicle, and unknown rule_text values are
verified at apply time instead.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kLA4K5wvUAdWG2epAVseV
@ben-f3

ben-f3 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@ben-f3 ben-f3 closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants