Skip to content

ScheduledReport

A Guardian scheduled send: run a SavedSearch on a calendar and send its rows to messaging connections or email. 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 scheduled send: run a SavedSearch on a calendar and send its rows to messaging connections or email. Each send is charged to the daily query budget like any search, and the plan caps how many are enabled.

apiVersion vulnetix.com/v1
kind ScheduledReport
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 ScheduledReport 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.
Applied after SavedSearch, MessagingConnection (deleted before them)
Terraform resource vulnetix_scheduled_report, imported by name (see Terraform and OpenTofu)
CLI vulnetix config apply, CLI v3.165.1 and later.
Pinned schema v1.15.0/ScheduledReport.schema.json
Newest schema latest/ScheduledReport.schema.json
First released in v1.3.0
Print the built-in copy vulnetix config schema ScheduledReport

Minimal

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

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: daily-dns-digest
spec:
  searchRef: dynamic-dns-lookups
  destination:
    kind: messaging
    connections: [secops-slack]

HCL (resource vulnetix_scheduled_report)

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

resource "vulnetix_scheduled_report" "daily_dns_digest" {
  name = "daily-dns-digest"
  destination = {
    connections = ["secops-slack"]
    kind        = "messaging"
  }
  search_ref = "dynamic-dns-lookups"
}

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/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: daily-dns-digest
spec:
  searchRef: dynamic-dns-lookups
  destination:
    kind: messaging
    connections: [secops-slack]
EOF

Advanced

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

YAML

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: weekly-console-sign-ins
  labels:
    team: secops
  annotations:
    ticket: https://jira.example.com/browse/SEC-2216
spec:
  displayName: Weekly console sign-ins
  searchRef: console-sign-ins
  repeat: weekly
  weekday: 1
  at: "08:00"
  zone: Australia/Melbourne
  rowsWindowMs: 604800000
  whenEmpty: all_clear
  enabled: true
  destination:
    kind: email
    emails: [secops@acme.example, ciso@acme.example]
    subject: Console sign-ins this week
  format:
    layout: table_chart
    rows: 20
    csv: true
    link: true
    query: true
---
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: monthly-dns-digest
spec:
  searchRef: dynamic-dns-lookups
  repeat: monthly
  monthday: 1
  at: "09:30"
  zone: UTC
  sincePrevious: true
  whenEmpty: skip
  enabled: true
  destination:
    kind: messaging
    connections: [secops-slack, soc-teams]
    subject: Dynamic DNS lookups this month
  format: { layout: summary, link: true }

HCL (resource vulnetix_scheduled_report)

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

resource "vulnetix_scheduled_report" "weekly_console_sign_ins" {
  name = "weekly-console-sign-ins"
  at   = "08:00"
  destination = {
    emails  = ["secops@acme.example", "ciso@acme.example"]
    kind    = "email"
    subject = "Console sign-ins this week"
  }
  display_name = "Weekly console sign-ins"
  enabled      = true
  format = {
    csv    = true
    layout = "table_chart"
    link   = true
    query  = true
    rows   = 20
  }
  repeat         = "weekly"
  rows_window_ms = 604800000
  search_ref     = "console-sign-ins"
  weekday        = 1
  when_empty     = "all_clear"
  zone           = "Australia/Melbourne"
  labels = {
    team = "secops"
  }
  annotations = {
    ticket = "https://jira.example.com/browse/SEC-2216"
  }
}

resource "vulnetix_scheduled_report" "monthly_dns_digest" {
  name = "monthly-dns-digest"
  at   = "09:30"
  destination = {
    connections = ["secops-slack", "soc-teams"]
    kind        = "messaging"
    subject     = "Dynamic DNS lookups this month"
  }
  enabled = true
  format = {
    layout = "summary"
    link   = true
  }
  monthday       = 1
  repeat         = "monthly"
  search_ref     = "dynamic-dns-lookups"
  since_previous = true
  when_empty     = "skip"
  zone           = "UTC"
}

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/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: weekly-console-sign-ins
  labels:
    team: secops
  annotations:
    ticket: https://jira.example.com/browse/SEC-2216
spec:
  displayName: Weekly console sign-ins
  searchRef: console-sign-ins
  repeat: weekly
  weekday: 1
  at: "08:00"
  zone: Australia/Melbourne
  rowsWindowMs: 604800000
  whenEmpty: all_clear
  enabled: true
  destination:
    kind: email
    emails: [secops@acme.example, ciso@acme.example]
    subject: Console sign-ins this week
  format:
    layout: table_chart
    rows: 20
    csv: true
    link: true
    query: true
---
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: monthly-dns-digest
spec:
  searchRef: dynamic-dns-lookups
  repeat: monthly
  monthday: 1
  at: "09:30"
  zone: UTC
  sincePrevious: true
  whenEmpty: skip
  enabled: true
  destination:
    kind: messaging
    connections: [secops-slack, soc-teams]
    subject: Dynamic DNS lookups this month
  format: { layout: summary, link: true }
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 ScheduledReport Always ScheduledReport.
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, and the default subject. Defaults to metadata.name.
spec.searchRef string yes pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ The metadata.name of the SavedSearch to run.
spec.repeat string no daily hourly, every_6h, daily, weekly, monthly
spec.at string no 08:00 pattern ^([01][0-9]|2[0-3]):[0-5][0-9]$ The time of day, 24-hour, in zone.
spec.zone string no UTC length 1 to 64 An IANA time zone, such as Australia/Sydney.
spec.weekday integer no 1 0 to 6 For weekly: 0 is Sunday.
spec.monthday integer no 1 1 to 28 For monthly. At most 28, so every month has the day.
spec.rowsWindowMs integer no 86400000 3600000 to 2678400000 How far back each send reads, in milliseconds: 1 hour to 31 days.
spec.sincePrevious boolean no false Read from the previous send instead of rowsWindowMs, so no row is reported twice.
spec.whenEmpty string no skip skip, all_clear skip sends nothing when there are no rows; all_clear sends a message saying so.
spec.enabled boolean no true
spec.destination object yes no other keys
spec.destination.kind string yes messaging, email
spec.destination.connections array of string no 1 to 10 items; items unique; each item: pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$
spec.destination.emails array of string no 1 to 20 items; items unique; each item: format email; length 0 to 254
spec.destination.subject string no length 1 to 160 Defaults to displayName.
spec.format object no no other keys
spec.format.layout string no table_chart table_chart, table, summary table_chart: a bar chart of the first measure and the table. table: the table only. summary: the row count only.
spec.format.rows integer no 20 1 to 100 Rows shown.
spec.format.csv boolean no true Attach a CSV of up to 1,000 rows. Email only.
spec.format.link boolean no true Link to the search in the console.
spec.format.query boolean no false Include the query text.

Rules

Conditions the schema enforces beyond each field’s own type. vulnetix config validate and the engine’s plan report a document that breaks one.

On Rule
spec.destination When kind is messaging: connections is required and emails is not allowed. Otherwise: emails is required and connections is not allowed.

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.
  • Order. Applied after SavedSearch and MessagingConnection, so a document that refers to one by metadata.name can be in the same apply. Deleted before them.
  • Second phase. This kind is not written inside the apply transaction. The other kinds apply and commit first, then each ScheduledReport 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 changes in place except searchRef: Guardian cannot point a send at another search, so a searchRef change creates the new send and then removes the old one.

Terraform and OpenTofu

The resource is vulnetix_scheduled_report 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_scheduled_report.

Import an object that already exists by its name:

# Import an existing ScheduledReport by its name (metadata.name).
terraform import vulnetix_scheduled_report.daily_dns_digest daily-dns-digest

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

More examples

examples/ScheduledReport/reports.yaml from Vulnetix/config-schemas:

# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/ScheduledReport.schema.json
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: weekly-console-sign-ins
spec:
  searchRef: console-sign-ins
  repeat: weekly
  weekday: 1
  at: "08:00"
  zone: Australia/Melbourne
  rowsWindowMs: 604800000
  whenEmpty: all_clear
  destination:
    kind: email
    emails: [secops@acme.example]
    subject: Console sign-ins this week
  format: { layout: table_chart, rows: 20, csv: true }
---
apiVersion: vulnetix.com/v1
kind: ScheduledReport
metadata:
  name: daily-dns-digest
spec:
  searchRef: dynamic-dns-lookups
  sincePrevious: true
  destination:
    kind: messaging
    connections: [secops-slack]
  format: { layout: summary }

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/ScheduledReport.schema.json, config-schemas/schemas/common.schema.json, config-schemas/examples/ScheduledReport/minimal.yaml, config-schemas/examples/ScheduledReport/advanced.yaml, config-schemas/examples/ScheduledReport/reports.yaml, terraform-provider-resolve/examples/resources/vulnetix_scheduled_report/minimal.tf, terraform-provider-resolve/examples/resources/vulnetix_scheduled_report/advanced.tf, vdb-site/docs/platform-iac-engine.md, vdb-site/api/internal/handler/config_engine_kinds.go, vdb-site/api/internal/config/siem_trigger.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.