Notifications
Starting with version 26, Step includes a flexible mechanism for sending notifications using various methods. Such notifications are meant to work in tandem with the Alerting Rules, allowing to define exactly which events and conditions will result in which notification being sent, with what data.
Introduction and Example
Step currently supports two kinds of notifications: good old E-Mails, and Webhook calls. The underlying data model is flexible enough to support other kinds of integrations, which might be implemented in the future if the need arises.
To understand how notifications are defined and processed in Step, and why they were implemented the way they are, let’s take one step back and examine what information is necessary to successfully send a notification using the supported mechanisms:
- In the case of an E-Mail, it is necessary to (at least) define:
- the server and connection properties (e.g. encryption) via which to send the mail
- potentially credentials for authenticating to the server
- the sender and recipient(s) of the mail
- the mail subject and body.
- potentially other (optional) information, such as CC: or BCC: recipients, etc.
- For a Webhook call, the required information is:
- the endpoint to connect to (i.e. a URL)
- the HTTP method to use (GET/POST)
- usually some kind of payload (POST body)
- potentially various HTTP headers, e.g. Authentication or other metadata
As is evident in particular in the case of an E-Mail, this information may concern different levels of abstraction or responsibility (as well as confidentiality): specifically, the connection and authentication properties are more “technical” and usually static, while at the same time being more sensitive from a security standpoint. Conversely, the mail subject and content are more dynamic and “user-accessible”. Sender and recipient information fall somewhere in between, and depending on your particular requirements could be rather static, or rather dynamic.
Let’s reconsider again the data required for sending an E-Mail, this time in tabular form. Imagine that this was a traditional paper form that needs to be filled in a company with a strictly hierarchical organization – who might be responsible for filling the individual fields?
Field Name | Value | Responsibility / set by |
---|---|---|
Mailserver | smtp://mail.example.org | Technical admin |
Login | me@example.org | Technical admin |
Password | secret! | Technical admin |
Mail From | step@example.org | Project owner |
Mail To | stepusers@example.org | Project owner |
Mail Subject | Hello from Step | Step user |
Mail Content | This is an example | Step user |
We have added here an additional column showing some fictitious responsibilities. A possible workflow then would be:
- The technical admin receives the completely empty form and fills in the first three fields, but leaves the rest empty.
- The form is handed over to the project owner who again fills the fields that he wants to have set.
- Finally, a user takes the almost completed form and fills in the final details.
- Once the form is completely filled, it can be handed over to the Email sending department who now has all the necessary information for sending the mail.
This is of course a contrived example, but it showcases an important aspect, namely that required data can be partially defined in multiple stages, and re-used or composed. Such (partially) defined notifications are called Notification Presets in Step. We also use the short form “Preset” throughout this document.
Notification Presets
Notification presets allow to pre-define data that will be used when sending notifications. Presets can thus be understood as a sort of (potentially layered) templates. This roughly corresponds to the sample use case presented in the introduction where notification data is filled in multiple stages.
Presets can be defined in two different places (see the dedicated section for the reasons):
- System-wide presets can only be defined by administrators and are found under Settings – Admin Settings – System Notification Presets.
- Project-wide presets are found under Settings – Project Notification Presets
Here is an example of the user interface for defining a Notification preset, further details will be provided below.
Preset Hierarchy
When defining a new Notification preset, in the very first step you will be required to select an existing preset which will serve as the parent preset, meaning that the parent preset provides the initial definition upon which the new preset will be based.
Notes:
- When starting from scratch (when no Presets exist at all), only the two presets named “built-in (E-Mail)” and “built-in (Webhook)” will be available for selection to create System Notification Presets. All custom presets will thus directly or indirectly depend on/extend these built-in presets.
- The built-in presets provide a “skeleton” of the fields required for the particular notification type. In other words, they define which fields exist, what they represent, and whether their value is required for dispatching a notification. However, they obviously do not define any concrete data.
- Technically, what is presented as “parent preset” in the user interface is termed “upstream preset” in the raw definitions. You will see this term used for instance in the Automation Package definitions. Conversely, “downstream (preset)” refers to notification presets which are based on/extend a particular preset.
Fields Definition and Protection
As mentioned before, the primary purpose of presets is to pre-define values for the data fields that make up a notification, so that users will not have to provide all of them every time they wish to make use of notifications. You could for instance create a preset that pre-fills the Mail sender and recipient addresses.
However, you have precise control over how exactly this data is defined and subsequently presented (or not!) to users using what is called the Field Protection, modifiable by using the control to the right of each field:
The possible protection values are:
- REDEFINABLE: This is the default protection. When this protection is selected and the preset in question is used, the respective field will be shown to the user, pre-filled with the data from the preset, but still modifiable by the user. In other words, the data defined in the preset will act as a default value that can be changed.
- READ-ONLY: When this protection is employed, the respective field, along with its data, will be shown to the user, but won’t be modifiable. This may be useful for informational purposes, to allow users to see the value that will be used (such as E-Mail recipients) even if they’re not able to change it.
- LOCKED: This is the strongest protection. It has the effect of fixing the value of a field, but also entirely removing the field from further inspection or modification. This protection is highly recommended for sensitive data, a prime example being the credentials required for sending E-Mails. However, it can also be used to “de-clutter” the user interface by hiding away fields which are irrelevant for your use cases. For instance, E-Mail presets contain a field for low-level Mail headers which is expected to be used only in very specific circumstances. By locking this field in a preset (even without assigning a value, as it is an optional field), your users won’t be bothered by its presence. The same could be done with the CC: and Bcc: fields, if you know you won’t be using them.
Inheriting and overriding data
As mentioned above, all presets are based on another preset (potentially a built-in one). This means that they “start” from the definition of that base preset, and are then logically “overlayed” on top of it. This has the following implications:
- Fields which are LOCKED (in the base preset) will no longer be shown at all. They will obviously continue to exist and keep their values internally, but the whole purpose of locking fields is to make them final and hide them.
- Fields which are READ-ONLY will be shown, but not be modifiable.
- Fields that are REDEFINABLE initially inherit their value from the base preset (which may be actually defined, or still empty), indicated by a blue “inherited” indicator on the top right. If you start to modify the value, this will explicitly overwrite the value with the newly defined one, and the indicator will change to an orange “override” one. To remove the override value, thus returning back to inheriting it from the base preset, simply click the small “X” next to the indicator.
Testing Notification Presets
If you want to test whether your definitions in the preset work, simply press the “Save and Test” button. (For technical reasons, the definition needs to be saved before being able to test it, which is made clear by the naming of the button).
Because presets do not necessarily need to include definitions for all fields (i.e., they explicitly allow to keep some values – even required ones – undefined if they are meant to be dynamic), you are taken to an intermediate dialog which allows you to complete any missing values:
Notes:
- Any changes that you make on the “Test” dialog are temporary and only affect the notification that will be sent for testing, they will not affect the preset.
- All mandatory fields must have values (either from the preset, or from this dialog) before the test notification can be sent.
- This dialog already takes into account the field protections from the preset. In other words, LOCKED fields will not be shown at all, and READ-ONLY fields will not be modifiable.
- If you are using placeholders for Alerting Rules (such as
${eventSummary}
) in your field definitions, these will be sent verbatim while testing the notification. In other words, the system cannot replace them by any concrete values at this stage; however, these replacements will obviously be performed when the notification is sent by an actual rule.
System Notification Presets
As mentioned, there are actually two places where Notification Presets can be defined:
- in the scope of individual projects, where they behave like all other entities such as plans, keywords etc.
- in the System Settings, by accessing the System Notification Presets entry.
Regular Step users are expected to define and use their presets using the “normal” (project) settings. However, there is an important – and intentional – restriction, described below.
As said, this is an intentional restriction. The rationale is that (especially for E-Mails), one normally does not want to allow just anybody to freely use any mail server they wish; rather, this is a setting that is usually limited to a very restricted set of servers and credentials, and should not be exposed to end users.
The suggested way to securely enabling E-Mail notifications is thus to simply create a System Notification Preset which defines the SMTP server (and very probably the credentials, though they may not be required depending on your mail server configuration), and applies the LOCKED protection to these fields, as shown in the example below. You may of course choose to pre-define and/or lock other fields as well, depending on your individual requirements.
For Webhook notifications, it is even simpler in the common case: it is sufficient to create a System Notification Preset with no fields defined or changed from the default. This simply allows for the use of Webhooks, leaving all the flexibility open for later usage.
Of course, you are free to define your system presets as openly or as restrictively as you choose, we only provided recommendations above. The important part is that ordinary presets are not allowed to be defined “from scratch”, but must be based on a System preset for the reasons outlined above – which in turn requires to define at least one System preset for the types of notifications you wish to use.
Notification Preset Effect and Usage
Notification Presets as such are only a means to an end: they are meant to provide blueprints that will allow users to focus on the important data in the places where notifications are actually sent, notably in Alerting Rules.
Think of Alerting Rules (or more specifically, the Notification Actions therein) as the place where the final content of the complete notification is fixed. It is at this stage that the final values of all fields are determined. A Notification action is required to be based on a Notification preset, but the amount of information that users will need to (or even can) provide at this stage depends on the definition of the selected preset itself. The user interface presented at this stage is a simplified version of the one that is used for defining presets, with unneeded functionality omitted. To showcase this, let’s consider two scenarios at the two extreme opposites of the spectrum:
- A Notification action that is based on a preset where all fields are effectively LOCKED (or READ-ONLY) will leave no customization options to the user. It can only be used as defined by the preset.
- A Notification action based on a preset where all fields are left REDEFINABLE without providing any values will still be completely customizable by users at this stage, in fact it will force the user to provide all values for at least the required fields.
Examples
Here are two screenshots showing examples. In the first case, all fields in the preset are LOCKED (and thus won’t be shown), with the following exceptions:
- From is READABLE and therefore shown, but not modifiable.
- To is REDEFINABLE with a default value set, so it can be changed for this individual notification.
- CC is REDEFINABLE with no value set. Since this is an optional field, users can (but don’t have to) provide values which will apply to this individual notification.
In the second example, a preset was used which defines nothing at all. Therefore, all fields would need to be filled at this stage:
Automation Package Integration
Project-level notification presets can also be defined (and used) in Automation Packages in a straightforward way as shown in the example snippet below (with fictitious data).
version: 1.0.0
name: "My package"
notificationPresets:
- EmailNotification:
presetName: "Sample mail"
upstreamPreset: "Mail"
subject:
data: "A fixed subject"
protection: READONLY
- WebhookNotification:
presetName: "Sample Webhook call"
upstreamPreset: "Webhook"
url:
data: "https://example.org"
method:
data: "POST"
body:
data: "{\"Hello\": \"World\"}"
headers:
description: "An example for data interpolation if this preset is used from an alerting rule"
data:
"X-Step-URL" : "${controllerUrl}"
alertingRules:
- eventClass: ExecutionEndedEvent
description: "Invoke a webhook on execution end"
actions:
- NotificationAction:
notification:
WebhookNotification:
upstreamPreset: "Sample Webhook call"
- eventClass: IncidentOpenedEvent
description: "Send mail on incident opened"
actions:
- NotificationAction:
notification:
EmailNotification:
upstreamPreset: "Sample Mail"
from:
data: "me@example.org"
to:
data:
- "you@example.org"
- "them@example.org"
bodyPlaintext:
data: "%{bindings}"
Note that the definitions in Automation Packages allow for even more flexibility than what is possible using the Web frontend, though that is probably rarely needed (which is why it was left out from the user interface). In particular, it is possible to override not only the actual data
and protection
settings of fields, but also their name
, description
, and required
attributes.
These advanced overrides are subject to some restrictions, namely:
- the redefinition is only possible if the field itself, after evaluation of the upstream preset, is still REDEFINABLE.
- the
required
attribute can only be overridden fromfalse
totrue
, not the other way around. This therefore allows to turn optional fields into mandatory ones, if you so desire.
Caveats and Known Limitations
There are some limitations mostly due to technical reasons. We are aware of them and will attempt to solve them in future releases.
- Notification Preset names must be globally unique (i.e. system-wide, across all projects and presets). We know that this is a limiting constraint, but it is not easily solvable at this time, so we believe it’s better to impose this constraint rather than have subtle bugs in the product. A simple strategy to avoiding name conflicts might be to use project-specific prefixes for the preset names.
- Care must be taken when changing the protection setting of Notification Presets which are already in use (i.e. used by downstream presets, or alerting rules): if a preset leaves a field REDEFINABLE, that field may be overridden by downstream definitions. If the protection is now changed to READ-ONLY or LOCKED, these downstream definitions could break because they are attempting to override a value where that is not allowed (anymore). We are working on detecting such cases and defining a strategy to handle them, but in the meantime, it is best to avoid such changes from REDEFINABLE to stronger protections for presets that are already referenced. Note that redefinitions from READ-ONLY to LOCKED (and vice versa) do not carry that risk.
- Notification Preset definitions in Automation Packages are ignored when executed in local or isolated mode, they can only be “actually” deployed.
Notification Fields
Below is a description of the individual fields available in the various notification types.
Mailserver
This required field defines the mail server to connect to when sending mails. It must contain a scheme prefix (e.g. smtps://
), a hostname (e.g. mail.mycompany.com
), and may optionally be followed by a colon and an explicit port (e.g. :2525
). The following schemes are supported:
smtp://
– unencrypted plaintext communication, default port is 25.smtps://
– connection-level TLS encryption encapsulating the SMTP protocol, default port is 465.smtp+starttls://
– opportunistic encryption employing the STARTTLS command for securing an otherwise unencrypted connection on the fly. Default port is 587.
The correct values to use depend on your mail server configuration, but typically either SMTP+STARTTLS or SMTPS (or both) are provided on the default ports by most servers.
SMTP Username and Password
These fields are technically optional, because not all mail servers enforce authentication – however there is a good chance that your mail server does, in which case you will need to set these fields. They define the credentials to use when authenticating to the mail server. Password authentication is the only supported authentication mechanism.
Subject
This required field defines the Mail subject.
Content
This is a required field, which contains the Mail content (body) in plaintext format. Please see the description of the next field about the behavior when both plaintext and HTML content is defined.
Content (HTML)
This field is optional and allows to specify HTML-formatted mail content. If an HTML-formatted content part is present, most mail readers will only show that content and ignore the plaintext part. However, it is best practice to send both parts nevertheless, so the plaintext content is still mandatory. You may either provide an unformatted version in the plaintext part, or (as is also common practice) simply a text like “This is an HTML mail. Please use an HTML-capable mail reader to view it”.
From
This required field specifies the mail sender as per the RFC 822 From
field. A number of common formats is supported, for example:
me@example.org
"My Full Name" <me@example.org>
To
This required field specifies the primary mail recipients. This is a list of mail addresses, and the same formats as for the From field are supported. At least one recipient must be specified.
Cc and Bcc
These optional fields (both accepting lists of E-Mail addresses in the common format) define Carbon Copy and Blind Carbon Copy mail recipients.
Headers
This is an optional field that allows to directly define any low-level RFC822 Mail headers as key/value pairs. As it is rarely used, we recommend to leave it empty and directly lock it in most cases.
Webhook
URL
This is a required field defining the URL to send a message to. The URL must start with either http://
or https://
.
Method
This required field sets the HTTP method to use when performing the Webhook call. Currently supported methods are GET
and POST
.
Headers
This is an optional field that allows to directly define any low-level HTTP headers as key/value pairs. Headers are often used to pass metadata such as authentication information or other additional details, depending on the requirements of the remote server.
Body
This is an optional field, normally not used for GET requests. For POST requests, it contains the payload to be sent to the remote endpoint.
Bindings and Substitutions
Especially in Alerting Rule Notification actions, some information that is relevant for notifications is dynamic depending on the event being processed, and is made available by Bindings. These bindings, or rather the runtime substitution using their concrete values, are supported in the following fields:
- E-Mail: Subject, Content, HTML Content, and Headers (header values only, not keys)
- Webhook: Body and Headers (header values only, not keys)