[cloud_security_posture] GCP lifecycle fields + metering_state transform for CSPM metering - #20736
Draft
seanrathier wants to merge 2 commits into
Draft
[cloud_security_posture] GCP lifecycle fields + metering_state transform for CSPM metering#20736seanrathier wants to merge 2 commits into
seanrathier wants to merge 2 commits into
Conversation
… for CSPM metering Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Maintains per-incarnation scan state (first/last seen, lifecycle) that the serverless CSPM metering task bills from, reading the resource.lifecycle.* fields the ingest pipeline indexes as of this version. Grouping on resource.lifecycle.incarnation is what makes spot-VM name reuse harmless: a re-created instance gets a fresh bucket instead of inheriting the previous instance's first_seen. Uses max aggregations plus a bucket_script rather than top_metrics. top_metrics emits the string "null" for a metric absent from a bucket, which the date/long destination mappings reject, dropping the whole document — that silently excluded every non-GCP resource and every never-stopped instance. KNOWN LIMITATION, do not merge as-is: installing this transform fails in serverless with a security_exception. run_as_kibana_system: false is set, but Fleet applies the installing user's secondary auth to putTransform and not to the destination-index create/delete, which are still attempted as elastic/kibana: action [indices:admin/create] is unauthorized for service account [elastic/kibana] on indices [logs-cloud_security_posture.metering_state-default] Verified against a local EPR serving this package to a serverless FTR Kibana. Needs a Fleet fix or a service-account grant before it can land. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
✅ Elastic Docs Style Checker (Vale)No issues found on modified lines! The Vale linter checks documentation changes against the Elastic Docs style guide. To use Vale locally or report issues, refer to Elastic style guide for Vale. |
Contributor
|
✅ All changelog entries have the correct PR link. |
Contributor
🚀 Benchmarks reportTo see the full report comment with |
💚 Build Succeeded
cc @seanrathier |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the package-side support for stateful serverless CSPM metering: the ingest pipeline indexes GCP compute lifecycle fields, and a new
metering_statetransform maintains the per-incarnation scan state that the metering task bills from.Warning
Draft — do not merge. The transform does not install in serverless; see Known limitation below. The ingest-pipeline commit is independently sound.
Related:
What's here
1. Ingest pipeline (
962667c) — lifts GCP compute lifecycle data out of the unindexedresource.rawpayload into indexedresource.lifecycle.*fields (status,incarnation,created_at,last_started_at,last_stopped_at,last_run_ms). Without this the metering transform has nothing to group or sort on.2.
metering_statetransform — a pivot transform writing one document per(resource.id, incarnation, sub_type, account, posture_type)intologs-cloud_security_posture.metering_state-default.Grouping on
resource.lifecycle.incarnationis the point: a spot VM that is destroyed and re-created under the same name starts a fresh bucket instead of inheriting the previous instance'sfirst_seen, sospan_msnever bridges two physically different machines.Two design notes worth review attention:
max+bucket_script, nottop_metrics.top_metricsemits the string"null"for a metric absent from a bucket, which thedate/longdestination mappings reject — dropping the whole document. That silently excluded every non-GCP resource and every never-stopped instance.maxis equivalent here because these timestamps are monotonic within one incarnation, and the incarnation is part of the group key.last_run_msis signed on purpose.stop - start; absent when the instance never stopped (defaultgap_policy: skip), negative when it was restarted after its last stop. The billing query uses that sign to tell a restarted-and-running instance from a stopped one, now that lifecycle status is no longer carried in the state document.Known limitation (blocks merge)
The transform fails to install in serverless:
_meta.run_as_kibana_system: falseis set, and Fleet does apply the installing user's secondary auth toputTransform(withdefer_validation: true). It does not apply it to the destination-index create/delete, which are still attempted aselastic/kibana. That account hasreadonlogs-*.*but nocreate_index/index/deleteon this pattern.The failure aborts the whole transform batch, so the pre-existing
misconfigurationtransform fails to install too, andPOST /api/fleet/package_policiesreturns 400.Needs one of: a Fleet change to pass secondary auth to the destination-index operations, or a service-account grant. Input from the Fleet team welcome — this is the part of the diagnosis I'm least certain of.
Test plan
Pipeline tests for the lifecycle fields are in
_dev/test/pipeline/test-gcp-lifecycle.json.Reproducing the install failure end to end:
elastic-package buildin this package.docker.elastic.co/kibana-ci/package-registry-distribution:litewithpackage_pathscovering both/packages/package-storageand a mount ofintegrations/build/packages.--xpack.fleet.registryUrlpointed at it andCLOUD_SECURITY_PLUGIN_VERSIONset to3.6.0.security_exceptionin the Kibana log.🤖 Generated with Claude Code