MessagingTemplate
An organisation's own message template, which a MessagingRoute uses instead of the system template for the event type. Fields, YAML, HCL and CLI samples, and how apply treats it.
An organisation’s own message template, which a MessagingRoute uses instead of the system template for the event type. One template renders for every provider: Slack, Teams, Discord and Google Chat get the title, summary, body, fields, actions and accent; Jira and GitHub Issues get the issue fields; a signed webhook gets the rendered text and, when asked, the event payload. Every text field is a Go text/template run in a sandbox: only the messaging functions are allowed, every value is escaped, and sizes are capped. Plan compiles each field and refuses a template with errors. Every change to content is saved as a new version, noted as applied as code, as a console edit is; earlier versions stay in the template’s history. Deleting it is refused while a route outside this apply still uses it.
apiVersion |
vulnetix.com/v1 |
kind |
MessagingTemplate |
| Group | Integrations |
| Status | Served. The config engine plans and applies it. |
| Objects per tenant | many, keyed by metadata.name |
| Token and role | An owner or admin session, or a vmt_ config management token with the owner or admin role that lists MessagingTemplate in its kinds. See Management tokens. |
| Terraform resource | vulnetix_messaging_template, imported by name (see Terraform and OpenTofu) |
| CLI | vulnetix config apply, CLI v3.168.0 and later. |
| Pinned schema | v1.15.0/MessagingTemplate.schema.json |
| Newest schema | latest/MessagingTemplate.schema.json |
| First released in | v1.5.0 |
| Print the built-in copy | vulnetix config schema MessagingTemplate |
Minimal
Only the fields the kind requires. From examples/MessagingTemplate/minimal.yaml.
YAML
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/MessagingTemplate.schema.json
apiVersion: vulnetix.com/v1
kind: MessagingTemplate
metadata:
name: plain-title
spec:
content:
title: "{{.event.title}}"
HCL (resource vulnetix_messaging_template)
# Only the arguments the kind requires. From config-schemas examples/MessagingTemplate/minimal.yaml.
resource "vulnetix_messaging_template" "plain_title" {
name = "plain-title"
content = {
title = "{{.event.title}}"
}
}
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/MessagingTemplate.schema.json
apiVersion: vulnetix.com/v1
kind: MessagingTemplate
metadata:
name: plain-title
spec:
content:
title: "{{.event.title}}"
EOF
Advanced
Every field the kind supports, with a when expression where it takes one. From examples/MessagingTemplate/advanced.yaml.
YAML
# yaml-language-server: $schema=https://github.com/Vulnetix/config-schemas/releases/latest/download/MessagingTemplate.schema.json
apiVersion: vulnetix.com/v1
kind: MessagingTemplate
metadata:
name: security-findings
labels:
team: security
annotations:
owner: appsec@acme.example
spec:
displayName: Security findings
description: Scan results for the security channel, with a link back to the scan.
eventScope:
- scan.completed
- scan.build_broken
baseSystemTemplate: generic
content:
title: "{{.event.title}}"
summary: "{{with .subject.label}}{{.}}{{end}}"
body: "{{range $k, $v := .data}}- **{{$k}}:** {{truncate 200 $v}}\n{{end}}{{with .mentions}}\n{{mentions .}}{{end}}"
fields:
- label: Severity
value: "{{severityEmoji .event.severity}} {{severityLabel .event.severity}}"
inline: true
actions:
- label: Open in Vulnetix
url: "{{.event.url}}"
accent: "{{.event.severity}}"
issue:
title: "[Vulnetix] {{.event.title}}"
body: "{{.event.title}}"
labels:
- vulnetix
- security
digest:
title: "{{.digest.count}} {{plural .digest.count \"event\" \"events\"}}"
item: "{{.event.title}}{{with .subject.label}}: {{.}}{{end}}"
webhook:
includePayload: true
HCL (resource vulnetix_messaging_template)
# Every argument the kind supports. From config-schemas examples/MessagingTemplate/advanced.yaml.
resource "vulnetix_messaging_template" "security_findings" {
name = "security-findings"
base_system_template = "generic"
content = {
accent = "{{.event.severity}}"
actions = [
{
label = "Open in Vulnetix"
url = "{{.event.url}}"
},
]
body = "{{range $k, $v := .data}}- **{{$k}}:** {{truncate 200 $v}}\n{{end}}{{with .mentions}}\n{{mentions .}}{{end}}"
digest = {
item = "{{.event.title}}{{with .subject.label}}: {{.}}{{end}}"
title = "{{.digest.count}} {{plural .digest.count \"event\" \"events\"}}"
}
fields = [
{
inline = true
label = "Severity"
value = "{{severityEmoji .event.severity}} {{severityLabel .event.severity}}"
},
]
issue = {
body = "{{.event.title}}"
labels = ["vulnetix", "security"]
title = "[Vulnetix] {{.event.title}}"
}
summary = "{{with .subject.label}}{{.}}{{end}}"
title = "{{.event.title}}"
webhook = {
include_payload = true
}
}
description = "Scan results for the security channel, with a link back to the scan."
display_name = "Security findings"
event_scope = ["scan.completed", "scan.build_broken"]
labels = {
team = "security"
}
annotations = {
owner = "appsec@acme.example"
}
}
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/MessagingTemplate.schema.json
apiVersion: vulnetix.com/v1
kind: MessagingTemplate
metadata:
name: security-findings
labels:
team: security
annotations:
owner: appsec@acme.example
spec:
displayName: Security findings
description: Scan results for the security channel, with a link back to the scan.
eventScope:
- scan.completed
- scan.build_broken
baseSystemTemplate: generic
content:
title: "{{.event.title}}"
summary: "{{with .subject.label}}{{.}}{{end}}"
body: "{{range $k, $v := .data}}- **{{$k}}:** {{truncate 200 $v}}\n{{end}}{{with .mentions}}\n{{mentions .}}{{end}}"
fields:
- label: Severity
value: "{{severityEmoji .event.severity}} {{severityLabel .event.severity}}"
inline: true
actions:
- label: Open in Vulnetix
url: "{{.event.url}}"
accent: "{{.event.severity}}"
issue:
title: "[Vulnetix] {{.event.title}}"
body: "{{.event.title}}"
labels:
- vulnetix
- security
digest:
title: "{{.digest.count}} {{plural .digest.count \"event\" \"events\"}}"
item: "{{.event.title}}{{with .subject.label}}: {{.}}{{end}}"
webhook:
includePayload: 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 MessagingTemplate |
Always MessagingTemplate. | |
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 120 | The name the console shows, unique among the organisation’s templates. Defaults to metadata.name. | |
spec.description |
string | no | length 0 to 1000 | What the template is for. | |
spec.eventScope |
array of string | no | 0 to 50 items; items unique; each item: pattern ^(\*|[a-z0-9_]+(\.[a-z0-9_]+)*(\.\*)?)$; length 0 to 128 |
The event types the template is meant for: a type (scan.completed), a family (pix.*), or *. The console uses it to offer the template; a route may still use it for any event. | |
spec.baseSystemTemplate |
string | no | pattern ^[a-z0-9_.]{1,64}$ |
The key of the system template this one was copied from (generic, findings.report, scan.build_broken and so on). It is recorded so the console can say when that system template has a newer version; it does not change the content. | |
spec.content |
object | yes | no other keys | The template itself. Each text field is a template over the event view (.event, .subject, .actor, .data, .mentions, and .digest for a digest). | |
spec.content.title |
string | yes | length 1 to 16384 | The message title. Required. | |
spec.content.summary |
string | no | length 0 to 16384 | One line under the title. | |
spec.content.body |
string | no | length 0 to 16384 | The message body, in markdown-lite. | |
spec.content.fields |
array of object | no | 0 to 25 items | Name and value pairs shown beside the body. At most 25. | |
spec.content.fields[].label |
string | yes | length 1 to 16384 | The field’s name. | |
spec.content.fields[].value |
string | yes | length 0 to 16384 | The field’s value. | |
spec.content.fields[].inline |
boolean | no | false |
Show the field beside the previous one where the provider can. | |
spec.content.actions |
array of object | no | 0 to 10 items | Buttons or links. At most 10. A URL that does not render to an https URL is dropped from the message. | |
spec.content.actions[].label |
string | yes | length 1 to 16384 | The button text. | |
spec.content.actions[].url |
string | yes | length 1 to 16384 | Where it goes. | |
spec.content.accent |
string | no | length 0 to 16384 | The colour bar: a severity (info, notice, warning, critical) or a #rrggbb colour, usually {{.event.severity}}. | |
spec.content.issue |
object | no | no other keys | What an issue tracker target gets. A field left out falls back to the message’s own. | |
spec.content.issue.title |
string | no | length 0 to 16384 | The issue title. | |
spec.content.issue.body |
string | no | length 0 to 16384 | The issue body. | |
spec.content.issue.labels |
array of string | no | 0 to 10 items; each item: length 1 to 16384 | Labels to put on the issue. At most 10. | |
spec.content.digest |
object | no | no other keys | How a batch of events is summed up when a route sends a digest. | |
spec.content.digest.title |
string | no | length 0 to 16384 | The digest title, over the batch view (.digest.count). | |
spec.content.digest.item |
string | no | length 0 to 16384 | One line per event in the batch. | |
spec.content.webhook |
object | no | no other keys | What a signed webhook target receives. | |
spec.content.webhook.includePayload |
boolean | no | false |
Send the event’s payload, reduced to the fields the catalogue allows, beside the rendered text. |
Applying this kind
- Command.
vulnetix config apply -f <file>; the CLI line above says from which release. Plan first withvulnetix config plan: it shows each object as create, update, delete or no change, with aplanHashthat apply then holds to. Apply writes in one transaction. - Manager. Each object records the manager that applied it (
terraform,consoleorgitops:<repo>).--prunedeletes only objects its own manager owns. See The manager and the config engine. - Status. Applied, Unchanged or Deleted, with no other status fields. The phases the engine reports are explained under status phases.
How apply treats it
The template is compiled at plan with the messaging centre’s template compiler, so an error shows before anything is written. Every change saves a new version.
Terraform and OpenTofu
The resource is vulnetix_messaging_template 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_messaging_template.
Import an object that already exists by its name:
# Import an existing MessagingTemplate by its name (metadata.name).
terraform import vulnetix_messaging_template.plain_title plain-title
Install, authentication and how state is read: Terraform and OpenTofu.
Check a file with vulnetix config validate -f <file>. See Validate documents. In an editor, start the file with the schema comment.