Skip to content

SavedSearch

A Guardian saved search. Fields, YAML, HCL and CLI samples, and how apply treats it.

Checked against config-schemas@v1.15.0, terraform-provider-resolve@82cb23c, cli@v4.9.1

A Guardian saved search. It is the source of a ScheduledReport, an AlertTrigger, or a DetectionRule with searchRef. The text is compiled when it is saved, so a search that does not compile is refused. The tenant always comes from the caller’s token. A tenant keeps at most 500. Deleting one that a ScheduledReport or AlertTrigger still uses is refused.

apiVersion vulnetix.com/v1
kind SavedSearch
Group SIEM
Status Served. The config engine plans and applies it.
Objects per tenant many, keyed by metadata.name
Token and role A vmt_ config management token that lists SavedSearch in its kinds. The owner or admin role writes; the member role reads only. A console session or an ApiKey is refused with kind_not_allowed, because the kind is written in Guardian with the caller’s own token.
Terraform resource vulnetix_saved_search, imported by name (see Terraform and OpenTofu)
CLI vulnetix config apply, CLI v3.165.1 and later.
Pinned schema v1.15.0/SavedSearch.schema.json
Newest schema latest/SavedSearch.schema.json
First released in v1.3.0
Print the built-in copy vulnetix config schema SavedSearch

Minimal

Only the fields the kind requires. From examples/SavedSearch/minimal.yaml.

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: dynamic-dns-lookups
spec:
  text: |
    dns_events
    | where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')

HCL (resource vulnetix_saved_search)

# Only the arguments the kind requires. From config-schemas examples/SavedSearch/minimal.yaml.

resource "vulnetix_saved_search" "dynamic_dns_lookups" {
  name = "dynamic-dns-lookups"
  text = "dns_events\n| where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')\n"
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: dynamic-dns-lookups
spec:
  text: |
    dns_events
    | where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')
EOF

Advanced

Every field the kind supports, with a when expression where it takes one. From examples/SavedSearch/advanced.yaml.

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: dynamic-dns-lookups
  labels:
    team: secops
  annotations:
    ticket: https://jira.example.com/browse/SEC-2215
spec:
  displayName: Dynamic DNS lookups
  mode: dsl
  text: |
    dns_events
    | where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')
  rangeMs: 86400000
---
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: console-sign-ins
spec:
  displayName: AWS console sign-ins
  mode: sigma
  text: |
    logsource:
      product: aws
      service: cloudtrail
    detection:
      selection:
        eventName: ConsoleLogin
      condition: selection
  rangeMs: 604800000

HCL (resource vulnetix_saved_search)

# Every argument the kind supports. From config-schemas examples/SavedSearch/advanced.yaml.

resource "vulnetix_saved_search" "dynamic_dns_lookups" {
  name         = "dynamic-dns-lookups"
  display_name = "Dynamic DNS lookups"
  mode         = "dsl"
  range_ms     = 86400000
  text         = "dns_events\n| where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')\n"
  labels = {
    team = "secops"
  }
  annotations = {
    ticket = "https://jira.example.com/browse/SEC-2215"
  }
}

resource "vulnetix_saved_search" "console_sign_ins" {
  name         = "console-sign-ins"
  display_name = "AWS console sign-ins"
  mode         = "sigma"
  range_ms     = 604800000
  text         = "logsource:\n  product: aws\n  service: cloudtrail\ndetection:\n  selection:\n    eventName: ConsoleLogin\n  condition: selection\n"
}

CLI (applies it)

export VULNETIX_CONFIG_TOKEN=vmt_...   # a config management token
vulnetix config apply -f - --manager gitops:acme/platform --auto-approve <<'EOF'
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: dynamic-dns-lookups
  labels:
    team: secops
  annotations:
    ticket: https://jira.example.com/browse/SEC-2215
spec:
  displayName: Dynamic DNS lookups
  mode: dsl
  text: |
    dns_events
    | where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')
  rangeMs: 86400000
---
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: console-sign-ins
spec:
  displayName: AWS console sign-ins
  mode: sigma
  text: |
    logsource:
      product: aws
      service: cloudtrail
    detection:
      selection:
        eventName: ConsoleLogin
      condition: selection
  rangeMs: 604800000
EOF

Fields

Paths use dots for nesting and [] for the items of a list. Required means required whenever the parent object is present. A default is what the server uses when the field is left out.

Field Type Required Default Allowed values Description
apiVersion string yes exactly vulnetix.com/v1 The document format version. Every kind in this release is vulnetix.com/v1.
kind string yes exactly SavedSearch Always SavedSearch.
metadata object yes no other keys
metadata.name string yes pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ The object’s name, unique per kind within a tenant. It is the natural key: plan, apply, export and the Terraform provider all address an object by kind and name.
metadata.org string no format uuid The tenant (organization UUID) the document belongs to. When set, plan and apply refuse to run against any other tenant.
metadata.labels object no map of string to string (length 0 to 256); keys match ^[a-z0-9]([a-z0-9._/-]{0,61}[a-z0-9])?$ Free key/value labels. Stored with the object, never interpreted by the server.
metadata.annotations object no map of string to string (length 0 to 4096) Free key/value notes for people and tools, such as a ticket link.
spec object yes no other keys
spec.displayName string no length 1 to 160 The name the console shows. Defaults to metadata.name.
spec.mode string no dsl dsl, sigma dsl: the Guardian search language. sigma: a Sigma rule’s detection, run as a search.
spec.text string yes length 1 to 16384 The search, in the language mode names.
spec.rangeMs integer no 86400000 60000 to 2592000000 How far back the search reads when it is opened or run by hand, in milliseconds: 1 minute to 30 days.

Applying this kind

  • Command. vulnetix config apply -f <file>; the CLI line above says from which release. Plan first with vulnetix config plan: it shows each object as create, update, delete or no change, with a planHash that apply then holds to. Apply writes in one transaction, except for the second phase below.
  • Manager. Each object records the manager that applied it (terraform, console or gitops:<repo>). --prune deletes only objects its own manager owns. See The manager and the config engine.
  • Second phase. This kind is not written inside the apply transaction. The other kinds apply and commit first, then each SavedSearch is written on its own, in Guardian. One that fails reports status.phase: Failed and a message, and nothing is recorded for it. The others stay applied and the apply answers 207. Plan again to see what is left. A single PUT from the Terraform provider answers 502 external_failed instead.
  • Status. A failed second-phase write reports phase Failed with a message. The phases the engine reports are explained under status phases.

How apply treats it

Written in Guardian, in the second phase; see SIEM kinds. Everything can change in place. Guardian refuses to delete a search that an AlertTrigger or a ScheduledReport still uses.

Terraform and OpenTofu

The resource is vulnetix_saved_search in the vulnetix/resolve provider. Its arguments are the spec in snake case, beside name, labels and annotations from metadata. The Minimal and Advanced HCL are above. The provider’s own reference is vulnetix_saved_search.

Import an object that already exists by its name:

# Import an existing SavedSearch by its name (metadata.name).
terraform import vulnetix_saved_search.dynamic_dns_lookups dynamic-dns-lookups

Install, authentication and how state is read: Terraform and OpenTofu.

More examples

examples/SavedSearch/searches.yaml from Vulnetix/config-schemas:

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/SavedSearch.schema.json
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: dynamic-dns-lookups
spec:
  displayName: Dynamic DNS lookups
  mode: dsl
  text: |
    dns_events
    | where qname endswith ('.duckdns.org', '.no-ip.org', '.ddns.net')
  rangeMs: 86400000
---
apiVersion: vulnetix.com/v1
kind: SavedSearch
metadata:
  name: console-sign-ins
spec:
  mode: sigma
  text: |
    logsource:
      product: aws
      service: cloudtrail
    detection:
      selection:
        eventName: ConsoleLogin
      condition: selection

Check a file with vulnetix config validate -f <file>. See Validate documents. In an editor, start the file with the schema comment.

Edit this pageSources: config-schemas/schemas/SavedSearch.schema.json, config-schemas/schemas/common.schema.json, config-schemas/examples/SavedSearch/minimal.yaml, config-schemas/examples/SavedSearch/advanced.yaml, config-schemas/examples/SavedSearch/searches.yaml, terraform-provider-resolve/examples/resources/vulnetix_saved_search/minimal.tf, terraform-provider-resolve/examples/resources/vulnetix_saved_search/advanced.tf, vdb-site/docs/platform-iac-engine.md, vdb-site/api/internal/handler/config_engine_kinds.go, vdb-site/api/internal/config/siem_search.go, vdb-site/api/internal/config/guardian.go
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.