Webhooks allow your tenant to invoke another web service when a security alert or a Centrify Analytics server event occurs on Centrify. For a security alert, the webhook will be invoked when the webhook's security level has been exceeeded.

Alerts and events are generated from data that has been passed from sensors to Centrify Analytics. Sensors are applications that work with data sources to retrieve information from different data sources and pass that information to Analytics.

This page describes how to programatically create and maintain webhooks.

Creating a Webhook and Working with Payload Variables

Creating the Webhook

Create a webhook by invoking the /rules/webhook endpoint and passing in the relevant information. In the following example, the url contains the URL of a Slack webhook to invoke, the event_type parameter specifies the type of event to watch, and the risk_level is set to Low:

POST https://mytenant.centrify.io/analytics/services/v1.0/rules/webhook HTTP/1.1

{  
   "name":"My Slack WebHook",
   "description":"",
   "url":"https://hooks.slack.com/services/T1C.../B9...",
   "method":"POST",
   "content_type":"application/json",
   "headers":"",
   "request_body":"{\n  \"attachments\": [\n    {\n      \"author_name\": \"Centrify Analytics\",\n      \"author_link\": \"https://${tenant_id}-${system.podscape}.${system.domain}/analytics\",\n      \"author_icon\": \"https://${tenant_id}-${system.podscape}.${system.domain}/analytics/ui/favicons/favicon.png\",\n      \"title\": \"Anomaly Session Found from Centrify Analytics\...",
   "enabled":true,
   "event_type":"Analytics.Server.AdaptiveSessionRecording",
   "risk_level":"Low"
}

The request_body parameter takes in the payload required by that webhook. The payload format is based on FreeMarker which allows the payload to be dynamically populated by including variables defined in Centrify Analytics which are substituted at invocation time with values pulled from the datasets defined in Analytics. Variables can represent system elements or events, and can be built-in (i.e. defined by Centrify) or user-defined.

In the request above to /rules/webhook, ${system-podscape} is an example of a system variable that will be substituted with a value when the webhook is invoked and the payload sent. See Getting a List of Variables for information on how to programmatically obtain a list of variables.

A 204 response indicates that the webhook was successfully created:

HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Fri, 18 May 2018 17:02:08 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

System and Event Variable Examples

The following is an example of using a variable to retrieve context from the triggering event when specifying the payload for a webhook:

${event.<COLUMN_NAME>}

The following are example variables that retrieve the system level context when specifying the payload for a webhook:

${system.domain} #The domain name of the current Analytic service that triggers the event
${system.podscape} #The podscape name of the current Analytic service that triggers the event

Utility Functions

This section lists some of the utility functions that can be used in the payload.

FreeMarker Builtin's
The FreeMarker built-in functions listed here can be used in the payload.

The following are examples of Analytics built-in functions that can be used.

Analytics Time Zone Built-in
utils.number_to_datetime_timezone converts a timestamp in milliseconds to a formatted data time string in a specific time zone.

${utils.number_to_datetime_timezone(<TIMESTAMP>, '<TIMEZONE>')
<TIMESTAMP>, timestamp in milliseconds

Where <TIMEZONE>, is the database timezone name.

For example:

e.g. ${utils.number_to_datetime_timezone(event_time, 'US/Pacific')

output: May 14, 2018 3:22 PM, PDT

Analytics Timestamp Builtin
utils.number_to_datetime_utc converts a timestamp in milliseconds to a formatted data time string in UTC.

${utils.number_to_datetime_utc(<TIMESTAMP>)
<TIMESTAMP>, timestamp in milliseconds

For example:

${utils.number_to_datetime_utc(event_time)

output: Mar 14, 2018 11:12 PM, UTC

Testing a Webhook

Test the connection to the webhook by invoking the /rules/webhook/test. Note: you can test the webhook connection before or after creating the webhook.

POST https://mytenant.centrify.io/analytics/services/v1.0/rules/webhook/test

{  
   "name":"My Slack WebHook",
   "description":"",
   "url":"https://hooks.slack.com/services/T0C...",
   "method":"POST",
   "content_type":"application/json",
   "headers":"",
   "request_body":"{\n  \"attachments\": [\n    {\n      \"autho...",
   "enabled":true,
   "event_type":"Analytics.Server.AdaptiveSessionRecording",
   "risk_level":"Low"
}

The result field in the response indicates if the webhook connection is functioning correctly:

{  
   "result":true,
   "http_status":200,
   "message":"ok"
}

Getting a List of Web Hooks

You can get detailed information for all of the existing webhooks on the tenant by invoking the /rules endpoint:

GET https://mytenant.centrify.io/analytics/services/v1.0/rules

The response contains a collection of objects with detailed information about each webhook:

[  
   {  
      "tenant_id":"ABC1234",
      "policy_id":"7bb7...",
      "name":"My Slack Test WebHook",
      "description":null,
      "rule":{  
         "filter_type":"com.centrify.platform.notification.rule.filter.EventTypeFilter",
         "filter_meta_data":{  
            "event_type":"Analytics.Server.AdaptiveSessionRecording"
         }
      },
      "actions":[  
         {  
            "action_type":"webhook",
            "action_meta_data":{  
               "headers":"",
               "method":"POST",
               "content_type":"application/json",
               "request_body":"{\n  \"attachments\": [\n    {\n      \"auth...",
               "url":"https://hooks.slack.com/services/T0C3..."
            },
            "action_provider":null,
            "provider_meta_data":{  

            }
         }
      ],
      "status":0,
      "created_by":"demo013",
      "updated_by":"demo013",
      "created_timestamp":1526662928102,
      "updated_timestamp":1526662928102,
      "new":false,
      "id":[  
         "AAA0004",
         "7bb...c"
      ]
   },
   ...
]

Getting a List of Variables

To get a list of variables, invoke the /dataset/system/models endpoint:

GET https://mytenant.centrify.io/analytics/services/v1.0/dataset/system/models

The columns field in the response contains the list of defined variables including the name and type for each. For example, the following model has a type set to SYSTEM indicating that the model contains system-defined variables and the sample shows three columns variables in the element: reason, app_type, and agent_id:

[  
   {  
      "model_mode":true,
      "node_name":"event",
      "description":"Centrify Event",
      "type":"SYSTEM",
      "multiple_snapshot":false,
      "model":{  
         "name":"event",
         "description":"Centrify Event",
         "columns":[  
            {  
               "type":"STRING",
               "name":"reason"
            },
            {  
               "type":"STRING",
               "name":"app_type"
            },
            {  
               "type":"STRING",
               "name":"agent_id"
            },
            ...
         ],

Deactivating and Reactivating a Web Hook

You can activate or deactivate a web hook by invoking the /rules/{id}/status endpoint:

POST https://mytenant.centrify.io/analytics/services/v1.0/rules/7bb.../status HTTP/1.1
HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Fri, 18 May 2018 17:03:24 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

Exporting and Importing a Web Hook

You can export webhooks to JSON by invoking the /file/export/rules/webhook/{name} endpoint. Pass in the IDs of the webhooks to export via the policy_ids body parameter and specify the base filename in the path (e.g. MyDemo) to use for the exported file:

POST https://mytenant.centrify.io/analytics/services/v1.0/file/export/rules/webhook/MyDemo

{  
   "policy_ids":[  
      "a5e7..."
   ],
   "export_url":true,
   "export_header":true
}

The response contains a .json file attachment with the exported webhook information. The webhook information is also included in the body of the response:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: attachment; filename="MyDemo.json"
Date: Fri, 18 May 2018 17:03:33 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Type: multipart/form-data
Content-Length: 3657

{
  "ruleActions": [
    {
      "tenantId": "ABC1234",
      "policyId": "a5e7...",
      "name": "MyDemo",
      "rule": {
        "filterType": "com.centrify.platform.notification.rule.filter.EventTypeFilter",
        "filterMetaData": {
          "event_type": "Analytics.Server.AdaptiveSessionRecording"
        }
      },
      "actions": [
        {
          "actionType": "webhook",
          "actionMetaData": {
            "headers": "Token token\u00...",
            "method": "POST",
            "content_type": "application/json",
            "request_body": "{\n  \"payload\": {\n    \"summary\": \"${intel_risk_level?cap_first} Risk: \u003...",
            "url": "https://events.pagerduty.com/v2/enqueue"
          },
          "providerMetaData": {}
        }
      ],
      "createdBy": "cia",
      "updatedBy": "cia"
    }
  ],
  "version": "0.9",
  "signature": "cfd8..."
}

Information that has been exported to a file using the /file/export/rules/webhook/{name} endpoint can be imported using the /file/import/rules/webhook endpoint:

POST https://mytenant.centrify.io/analytics/services/v1.0/file/import/rules/webhook

Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykmkpXEKtCNf6UQO0

------WebKitFormBoundarykmkpXEKtCNf6UQO0
Content-Disposition: form-data; name="file"; filename="MyDemo.json"
Content-Type: application/json

{  
   "ruleActions":[  
      {  
         "tenantId":"ABC1234",
         "policyId":"a5e...",
         "name":"PageDuty Demo",
         "rule":{  
            "filterType":"com.centrify.platform.notification.rule.filter.EventTypeFilter",
            "filterMetaData":{  
               "event_type":"Analytics.Server.AdaptiveSessionRecording"
            }
         },
         "actions":[  
            {  
               "actionType":"webhook",
               "actionMetaData":{  
                  "headers":"Token token=XKup...",
                  "method":"POST",
                  "content_type":"application/json",
                  "request_body":"{\n  \"payload\": {\n    \"summary\": \"${intel_risk_level?cap_first} Risk: <#if event_na...",
                  "url":"https://events.pagerduty.com/v2/enqueue"
               },
               "providerMetaData":{  

               }
            }
         ],
         "createdBy":"cia",
         "updatedBy":"cia"
      }
   ],
   "version":"0.9",
   "signature":"cfd8..."
}
------WebKitFormBoundarykmkpXEKtCNf6UQO0--

A response code of 200 indicates that the webhook was successfully imported:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Date: Fri, 18 May 2018 17:03:52 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Length: 0

Deleting a Webhook

You can delete an existing webhook by invoking the /rules/{id} endpoint and passing the ID of the webhook to delete via the id path parameter:

DELETE https://mytenant.centrify.io/analytics/services/v1.0/rules/a5e...
HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Fri, 18 May 2018 17:04:46 GMT
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

Try the API in Postman:
Try the API in Postman.
Click here for help with using our sample Postman collection.

Additional Examples

The following examples show how to configure Centrify to invoked third-party webhooks:

Webhooks