Actions
FIFO publish action
The purpose of this action is to publish to a Live Objects FIFO when a trigger is activated. FIFO publish is a routing feature without mustache templating (i.e. the entire data message or event is published in the FIFO, you can’t template it).
The API to manage FIFO is detailed in swagger.
{
"fifoName": "destinationfifo",
"noRetention": false
}
| Field | Description |
|---|---|
fifoName |
Name of the FIFO that will receive the triggered message |
noRetention |
If true, messages published to the FIFO from this action will not be stored; they will be immediately dropped if no subscriber is consuming from the FIFO at the time the messages are published. |
{
"name": "push data new to fifo",
"enabled": true,
"triggers": {
"dataMessage": {
"version": 1
}
},
"actions": {
"fifoPublish": [{"fifoName":"mydata"}]
}
}
{
"name": "push data new to fifo",
"enabled": true,
"triggers": {
"dataMessage": {
"version": 1,
"filter": {
"deviceIds": ["urn:lo:nsid:mqtt:deviceId2"]
}
}
},
"actions": {
"fifoPublish": [{
"fifoName": "mydata",
"noRetention": true
}]
}
}
Creating a FIFO publish action will automatically create the corresponding FIFO if it does not already exist. The total number of FIFO is limited depending on your offer so you may need to remove existing action policy with FIFO publish action to create new ones.
By default, a FIFO will store messages for a few days depending on your offer. If no subscriber consumes the messages during this period, they will be dropped. However, storing messages coming from an action policy can be disabled by setting the noRetention field to true. In this case, if no subscriber is consuming from the FIFO at the time messages are published, these messages will be immediately dropped.
|
If the FIFO messages published from an action are not consumed for 7 consecutive days, or if the targeted FIFO has been deleted; the ActionPolicy will be disabled. Its suspension field will provide additional details. |
Http Push action
The purpose of this action is to do an HTTP POST to a given URL with custom headers and a custom body. The body can be templated using the Mustache templating syntax.
Depending on the user needs, a retry policy can be enabled to be more resilient to listening endpoint downtimes.
{
"webhookUrl": String,
"headers": Map of <String,List of String> ({"key": ["value1","value2",...]}),
"retryOnFailure": boolean,
"jsonPath": String,
"content": String
}
| field name | is required | description |
|---|---|---|
webhookUrl |
required |
defines the location of the webhook (only the secured ports 443, 8443 and 9243 are allowed, the insecure ports ex: 80 or 8080 are not supported). |
headers |
optional |
defines custom headers that are sent along the HTTP POST request. |
signingSecret |
optional |
Secret used to compute an HMAC signature of the HTTP POST request. The signature is added as a header for authenticity and integrity validation. |
retryOnFailure |
optional |
Enables retry on failure policy (see related section) |
jsonPath |
optional |
Select a part of the triggering data using a jsonPath syntax. This selected data will be used as the root of the template datacontext. This field can be omitted when you want to work with the whole data in template. |
content |
optional |
A string representing a Mustache template. This template will be rendered as the request body. |
{
"name": "some_user_friendly_name",
"enabled": true,
"triggers": {
"dataMessage": {
}
},
"actions": {
"httpPush": [{
"webhookUrl": "https://hooks.myservice.com/services/SOMEWEBHOOKREFERENCE",
"headers": {"authorization": ["Bearer 00000000-0000-0000-0000-000000000000"]},
"retryOnFailure": true,
"content": "{\"text\": \"data pushed to stream : {{streamId}}, at {{timestamp}}\"}"
}]
}
}
Generated headers
Every Http Push request contains a header with the action policy id.
If the id of an action policy is 6c95837b-251d-41d8-95f1-42facdf8e71e. The http push will have the following header:
x-orange-lo-policy-id:6c95837b-251d-41d8-95f1-42facdf8e71e
Every Http Push request contains a header with an id that identifies that push uniquely (this id will be kept across retries in case of errors). This id can be used to identify if a message has been delivered multiple times to the webhook.
x-orange-lo-message-id: 00000000-0000-0000-0000-000000000000
If a signingSecret is configured, this header is added with the Unix epoch timestamp (in seconds). See below for how to use it to validate the request.
If a signingSecret is configured, this header is added with an HMAC-SHA-256 signature (hex-encoded). See below for how to use it to validate the request.
x-orange-hmac-sha256-signature: 28208ff5566f18c2ae740294cf77fd683000947c64c83156969b5a45dfba4b17
|
Live Objects will try to validate the body of the HTTP POST as JSON object and will set the request Content-Type header accordingly:
|
HTTP Push signature verification process
If a signingSecret is configured, Live Objects signs the HTTP POST message using the secret key (signingSecret) and the HMAC-SHA-256 algorithm, encodes the resulting signature in hex, and includes it in the x-orange-hmac-sha256-signature header. To mitigate replay attacks, Live Objects also adds a x-orange-timestamp-epoch-seconds header.
The webhook server should validate the request by computing the signature and comparing it with the one provided in the headers using the following steps.
-
Store the
signingSecretsecurely on your server -
Gather inputs as UTF-8 strings:
-
originid=x-orange-lo-policy-idheader value -
messageuuid=x-orange-lo-message-idheader value -
epochseconds=x-orange-timestamp-epoch-secondsheader value -
requestbody= exact HTTP POST body as a string (UTF-8)
-
-
Check freshness: compare
epochsecondswith the server’s local time; it should be within an acceptable timeframe (e.g., 3–5 minutes). Using an NTP-synchronized clock is recommended. -
Build the input string with colon separators, without extra spaces:
epochseconds:originid:messageuuid:requestbody -
Compute the HMAC using HMAC-SHA-256 with
signingSecretas key, then hex-encode the result. -
Compare the computed signature to the
x-orange-hmac-sha256-signatureheader value. Use a constant-time comparison if possible. If they match and the timestamp is within the allowed window, the request is considered authentic and unmodified.
Example
-
epochseconds: 1710000000 (GMT: Saturday 9 March 2024 16:00:00)
-
originid: origin-123
-
messageuuid: uuid-456
-
requestbody: {"foo":"bar"}
-
signingSecret: mySecretKey
String to sign: 1710000000:origin-123:uuid-456:{"foo":"bar"}
Signature (hex): 28208ff5566f18c2ae740294cf77fd683000947c64c83156969b5a45dfba4b17
General documentation regarding webhooks and HMAC:
Policy and error management
When an error message is sent back by the destination resource, a retry policy will occur (if configured when the Http Push Action was created). The Http Push action will be retried depending on the HTTP error code sent back from the destination resource to Live Objects.
| HTTP ERROR CLASS | Error handling mode |
|---|---|
4xx |
Unrecoverable error: discard Http Push action |
5xx |
Recoverable error: retry Http Push action execution (if retryPolicy is true) otherwise discard the Http Push action execution |
When enabled, the retry policy will try to regularly post a request to the resource referenced by the Http Push action url parameter. These retries will be attempted over around twenty-four hours. The retry pattern is subject to change, but it currently follows:
| # of retry | delay between retry |
|---|---|
3 |
5 seconds |
3 |
5 minutes |
12 |
2 hours |
In the case where the retries are unsuccessful, the Http Push action execution is discarded.
|
If the HttpPush error rate is too high (> 90%) for 7 consecutive days; the ActionPolicy will be disabled. Its suspension field will provide additional details. |
Message Overflow
If the targeted servers for HTTP Push (webHook) are down or slow, HTTP push requests will be buffered. The buffer size, mutualized between all your HTTP Push action policies can contain up to 10.000 requests. If this limit is reached, the oldest request will be discarded first and an AuditLog will be recorded.
As a consequence, if more than 10.000 messages are waiting to be pushed to your HTTP servers, then some of them will start to be dropped. The messages pending retry are not included in this amount.
There are 2 typical cases where this can happen :
-
the HTTP server is not available, then each message needs to wait for the 5s timeout before continuing its retry cycle
-
the HTTP server has a slower response time than the rate at which messages are being pushed
If this happens, the number of pending messages will increase up to 10.000 and the overflow mechanism will be triggered.
In order to decrease the risk of congestion and overflow, HTTP Push requests are performed with some parallelism when several messages are pending (up to 10 concurrent requests).
Security considerations
A secure resource endpoint (HTTPS) should always be used. Using a non secure endpoint (HTTP) is a security issue as the data exchange between Live Objects and the resource endpoint will not be encrypted. This is especially true when leveraging the custom headers mechanisms to pass authentication token.
As a general recommendation, when using a custom authorization header, consider it insecure and be sure to give the token/credentials the least permissions. It should only be able to do an HTTP POST on the defined resource location.
Http Push Results
Each Http Push action with an ERROR will generate an audit log message. This can help analyze traffic problems.
The solution is to:
-
use the Audit Log REST APIs or web portal
{
"tenantId": "httppush550b5cd6-b8c6-49a4-baa9-d3c21a84202d",
"httpPushRequest": {
"url": "http://localhost:14567",
"retryOnFailure": false,
"headers": null,
"requestBody": "{\"x\":0}",
"messageUUID": "b5540f77-bbc8-42c8-9942-35c0b133a689"
},
"success": false,
"responseStatusCode": 400,
"responseBody": "KO",
"errorMessage": "an error message"
}
About HTTPS certificate
When using https to push data to a webhook, the certification chain must be valid according to the default Java 8 JVM implementation. Any self signed certificate or certificate issued by an unknown organization (according to the JAVA 8 JVM) presented by a webhook will be refused and the http push action will not be executed.
About HTTP/HTTPS authorized ports and reachable IP address
|
| If you have a 403 forbidden error, you need to check if you have using a right port number. In the other hand, the remote server must allow the port number that you are using. |
HTTP_PUSH vs FIFO
| Performance | Security | Resilience | Easy to integrate | Keep message sequence | Recommended for | |
|---|---|---|---|---|---|---|
HTTP PUSH |
➖ : significant protocol overhead (http headers, 200 OK responses) ➖ : retries increases the load |
➖ : requires to open and secure a TCP port on the Internet to receive traffic. |
➖ : buffer of 10K messages max / account, 24h of retry max |
➕ : http very well known in the developers community ➕ : compatible with stateless servers |
➖ : Retry policy changes significantly the sequencing of messages. ➖ : Complicates the processing of events in the customer’s IT (typically state processing) |
prototypes and small applications with low quality of service constraints |
MQTTs Application |
➕ : messages are acked or stay in the FIFO, no need of retries ➕ : optimized protocol overhead |
➕➕ : no incoming connections from the Internet to your server, only outgoing, strong authentication supported on Live Objects (TLS client certificate) |
➕ : buffer (FIFO queue) for up to 7 days of message retention in the FIFOs |
➖ : requires the integration of a mqtt client (less known in the web developers community). See our code samples here. |
➕ : FIFO preserves the sequencing of messages, facilitates the processing of events in the client’s IT (typically state processing) |
for large deployments |
Azure Event Hubs action
The purpose of this action is to push a message into Azure Event Hubs service. The body can be templated using the Mustache templating syntax.
Depending on the user needs, a retry policy can be enabled to be more resilient to listening endpoint downtimes.
Error management, message overflow, rate limiting, auditlog, certificate aspects are identical to http push action.
{
"eventHubsNamespace": "myEventHubsNamespace",
"eventHubName":"myEventHubName",
"sharedAccessKeyName":"mySharedAccessKeyName",
"sharedAccessKey":"mySharedAccessKey",
"content": "{\"temperature\": {{temp}} }",
"jsonPath":"value",
"retryOnFailure":false
}
| field name | is required | description |
|---|---|---|
eventHubsNamespace |
required |
The Event Hubs namespace where is located the targeted Event Hub. |
eventHubName |
required |
The name of the targeted Event Hub. |
sharedAccessKeyName |
required |
The name of the shared access policy of the targeted Event Hub. |
sharedAccessKey |
required |
The shared access key of the shared access policy. |
jsonPath |
optional |
The json path to extract from the considered message (or event), it will be taken as the root datacontext object when combined with a mustache template in content. |
content |
optional |
A raw string or a mustache (https://mustache.github.io/mustache.5.html) template describing the webhook body. If empty, the raw event will be used. |
retryOnFailure |
required |
Indicate if a retry policy should be set up in case of a delivery failure. |