mirror of
https://github.com/zulip/zulip.git
synced 2025-11-14 10:57:58 +00:00
Add a Splunk webhook integration.
Add a webhook to create messages from Splunk search alerts. The search alert JSON includes the first search result and a link to view the full results. The following fields are used: * search_name - the name of the saved search * results_link - URL of the full search results * host - the host the search result came from * source - the source file on that host * _raw - the raw text of the logged event. The Zulip message contains: * search name * host * source * raw The destination stream and message topic are configurable: the default stream is "splunk" and the default topic "Splunk Alert". If the topic is not provided in the URL, the search name is used instead (truncated if too long. If a needed field is missing, a default value is used instead. Example: "Missing source" It is possible to configure a Splunk search to not include some values, so I've provided defaults rather than return an error for missing data. In practice, these fields are unlikely to be deliberately suppressed. Note: alerts are only available for Splunk servers using a valid trial, developer, or paid license. I've added tests for the normal case of one search result, the topic from the search name, and for a search missing one of the fields used. Tested using Splunk Enterprise 6.5.1. Fixes #3477
This commit is contained in:
BIN
static/images/integrations/logos/splunk.png
Normal file
BIN
static/images/integrations/logos/splunk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
BIN
static/images/integrations/splunk/splunk_configure_url.png
Normal file
BIN
static/images/integrations/splunk/splunk_configure_url.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
BIN
static/images/integrations/splunk/splunk_message.png
Normal file
BIN
static/images/integrations/splunk/splunk_message.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
static/images/integrations/splunk/splunk_save_as_alert.png
Normal file
BIN
static/images/integrations/splunk/splunk_save_as_alert.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
46
zerver/fixtures/splunk/splunk_long_search_name.json
Normal file
46
zerver/fixtures/splunk/splunk_long_search_name.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "this-search's-got-47-words-37-sentences-58-words-we-wanna-know-details-of-the-search-time-of-the-search-and-any-other-kind-of-thing-you-gotta-say-pertaining-to-and-about-the-search-I-want-to-know-authenticated-user's-name-and-any-other-kind-of-thing-you-gotta-say",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
45
zerver/fixtures/splunk/splunk_missing_host.json
Normal file
45
zerver/fixtures/splunk/splunk_missing_host.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "sudo",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
45
zerver/fixtures/splunk/splunk_missing_raw.json
Normal file
45
zerver/fixtures/splunk/splunk_missing_raw.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "sudo",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
45
zerver/fixtures/splunk/splunk_missing_results_link.json
Normal file
45
zerver/fixtures/splunk/splunk_missing_results_link.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "sudo",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
45
zerver/fixtures/splunk/splunk_missing_search_name.json
Normal file
45
zerver/fixtures/splunk/splunk_missing_search_name.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
45
zerver/fixtures/splunk/splunk_missing_source.json
Normal file
45
zerver/fixtures/splunk/splunk_missing_source.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "sudo",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
46
zerver/fixtures/splunk/splunk_search_one_result.json
Normal file
46
zerver/fixtures/splunk/splunk_search_one_result.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "sudo",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
46
zerver/fixtures/splunk/splunk_short_search_name.json
Normal file
46
zerver/fixtures/splunk/splunk_short_search_name.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"results_link": "http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now",
|
||||||
|
"app": "search",
|
||||||
|
"result": {
|
||||||
|
"timestartpos": "0",
|
||||||
|
"_serial": "2",
|
||||||
|
"splunk_server": "myserver",
|
||||||
|
"date_month": "january",
|
||||||
|
"USER": "",
|
||||||
|
"date_second": "32",
|
||||||
|
"source": "/var/log/auth.log",
|
||||||
|
"timeendpos": "15",
|
||||||
|
"_si": [
|
||||||
|
"myserver",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"punct": "___::_-_:_(:):_____",
|
||||||
|
"host": "myserver",
|
||||||
|
"TTY": "",
|
||||||
|
"_raw": "Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root",
|
||||||
|
"_sourcetype": "syslog",
|
||||||
|
"index": "main",
|
||||||
|
"date_minute": "14",
|
||||||
|
"date_year": "2017",
|
||||||
|
"_kv": "1",
|
||||||
|
"process": "sudo",
|
||||||
|
"PWD": "",
|
||||||
|
"pid": "",
|
||||||
|
"_time": "1483557272",
|
||||||
|
"uid": "",
|
||||||
|
"date_zone": "local",
|
||||||
|
"sourcetype": "syslog",
|
||||||
|
"_indextime": "1483557272",
|
||||||
|
"date_hour": "11",
|
||||||
|
"date_mday": "4",
|
||||||
|
"linecount": "",
|
||||||
|
"eventtype": "",
|
||||||
|
"COMMAND": "",
|
||||||
|
"_eventtype_color": "",
|
||||||
|
"date_wday": "wednesday",
|
||||||
|
"_confstr": "source::/var/log/auth.log|host::myserver|syslog"
|
||||||
|
},
|
||||||
|
"sid": "rt_scheduler__admin__search__sudo_at_1483557185_2.2",
|
||||||
|
"search_name": "This search's name isn't that long",
|
||||||
|
"owner": "admin"
|
||||||
|
}
|
||||||
@@ -150,6 +150,7 @@ WEBHOOK_INTEGRATIONS = [
|
|||||||
WebhookIntegration('semaphore'),
|
WebhookIntegration('semaphore'),
|
||||||
WebhookIntegration('sentry'),
|
WebhookIntegration('sentry'),
|
||||||
WebhookIntegration('solano', display_name='Solano Labs'),
|
WebhookIntegration('solano', display_name='Solano Labs'),
|
||||||
|
WebhookIntegration('splunk', display_name='Splunk'),
|
||||||
WebhookIntegration('stash'),
|
WebhookIntegration('stash'),
|
||||||
WebhookIntegration('stripe', display_name='Stripe'),
|
WebhookIntegration('stripe', display_name='Stripe'),
|
||||||
WebhookIntegration('taiga'),
|
WebhookIntegration('taiga'),
|
||||||
|
|||||||
0
zerver/webhooks/splunk/__init__.py
Normal file
0
zerver/webhooks/splunk/__init__.py
Normal file
56
zerver/webhooks/splunk/doc.html
Normal file
56
zerver/webhooks/splunk/doc.html
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<p>
|
||||||
|
See your Splunk Search alerts in Zulip!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
First, create the stream you'd like to use for Splunk notifications,
|
||||||
|
and subscribe all interested parties to this stream. We recommend the
|
||||||
|
stream name <code>splunk</code>, although you may choose another stream
|
||||||
|
if you prefer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Next, in the Splunk search app, execute the search you'd like to alert on
|
||||||
|
and then save it as an alert:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="/static/images/integrations/splunk/splunk_save_as_alert.png"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Name and configure your search in the "Settings" and "Trigger Conditions"
|
||||||
|
sections of the "Save As Alert" dialog box. In the "Trigger Actions" section,
|
||||||
|
click "Add Actions" and select "Webhook" to add a webhook action. Put the
|
||||||
|
Zulip Splunk webhook URL and your API key in the "URL" field, along with
|
||||||
|
your desired stream and (optional) topic name. If you do not specify a stream,
|
||||||
|
your messages will use the default stream `splunk`. If you do not specify a topic,
|
||||||
|
the name of the search is used (truncated to fit if needed.)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Example:
|
||||||
|
<code>{{ external_api_uri_subdomain }}/v1/external/splunk?api_key=abcde&stream=splunk&topic=alerts</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When you are done, it should look like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img src="/static/images/integrations/splunk/splunk_configure_url.png"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Click Save to save the alert. You can create as many searches with alert
|
||||||
|
actions as you like, with whatever stream and topic you choose. Update your
|
||||||
|
webhook URL as appropriate for each one, and make sure the stream exists.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>Congratulations! You're done!</b><br/> When your search triggers an
|
||||||
|
alert, you'll see a notification like this:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img class="screenshot" src="/static/images/integrations/splunk/splunk_message.png"/>
|
||||||
|
</p>
|
||||||
139
zerver/webhooks/splunk/tests.py
Normal file
139
zerver/webhooks/splunk/tests.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from typing import Text
|
||||||
|
from zerver.lib.test_classes import WebhookTestCase
|
||||||
|
|
||||||
|
class SplunkHookTests(WebhookTestCase):
|
||||||
|
|
||||||
|
STREAM_NAME = 'splunk'
|
||||||
|
TOPIC = u"Default Topic"
|
||||||
|
URL_TEMPLATE = "/api/v1/external/splunk?api_key={api_key}&stream={stream}&topic={topic}"
|
||||||
|
FIXTURE_DIR_NAME = 'splunk'
|
||||||
|
|
||||||
|
# override the base class behavior so we can include TOPIC
|
||||||
|
def build_webhook_url(self):
|
||||||
|
# type: () -> Text
|
||||||
|
api_key = self.get_api_key(self.TEST_USER_EMAIL)
|
||||||
|
return self.URL_TEMPLATE.format(stream=self.STREAM_NAME,
|
||||||
|
api_key=api_key,
|
||||||
|
topic=self.TOPIC)
|
||||||
|
|
||||||
|
def test_splunk_search_one_result(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
# construct the URL used for this test
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
# define the expected message contents
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[sudo](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
# using fixture named splunk_search_one_result, execute this test
|
||||||
|
self.send_and_test_stream_message('search_one_result',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_short_search_name(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
# don't provide a topic so the search name is used instead
|
||||||
|
self.URL_TEMPLATE = "/api/v1/external/splunk?api_key={api_key}&stream={stream}"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"This search's name isn't that long"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[This search's name isn't that long](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('short_search_name',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_long_search_name(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
# don't provide a topic so the search name is used instead
|
||||||
|
self.URL_TEMPLATE = "/api/v1/external/splunk?api_key={api_key}&stream={stream}"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"this-search's-got-47-words-37-sentences-58-words-we-wanna..."
|
||||||
|
expected_message = u"Splunk alert from saved search\n[this-search's-got-47-words-37-sentences-58-words-we-wanna-know-details-of-the-search-time-of-the-search-and-any-other-kind-of-thing-you-gotta-say-pertaining-to-and-about-the-search-I-want-to-know-authenticated-user's-name-and-any-other-kind-of-thing-you-gotta-say](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('long_search_name',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_missing_results_link(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[sudo](Missing results_link)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('missing_results_link',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_missing_search_name(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[Missing search_name](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('missing_search_name',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_missing_host(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[sudo](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: Missing host\nsource: /var/log/auth.log\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('missing_host',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_missing_source(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[sudo](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: Missing source\n\nraw: Jan 4 11:14:32 myserver sudo: pam_unix(sudo:session): session closed for user root"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('missing_source',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def test_splunk_missing_raw(self):
|
||||||
|
# type: () -> None
|
||||||
|
|
||||||
|
self.TOPIC = u"New Search Alert"
|
||||||
|
self.url = self.build_webhook_url()
|
||||||
|
|
||||||
|
expected_subject = u"New Search Alert"
|
||||||
|
expected_message = u"Splunk alert from saved search\n[sudo](http://example.com:8000/app/search/search?q=%7Cloadjob%20rt_scheduler__admin__search__sudo_at_1483557185_2.2%20%7C%20head%201%20%7C%20tail%201&earliest=0&latest=now)\nhost: myserver\nsource: /var/log/auth.log\n\nraw: Missing _raw"
|
||||||
|
|
||||||
|
self.send_and_test_stream_message('missing_raw',
|
||||||
|
expected_subject,
|
||||||
|
expected_message,
|
||||||
|
content_type="application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
def get_body(self, fixture_name):
|
||||||
|
# type: (Text) -> Text
|
||||||
|
return self.fixture_data("splunk", fixture_name, file_type="json")
|
||||||
44
zerver/webhooks/splunk/view.py
Normal file
44
zerver/webhooks/splunk/view.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Webhooks for external integrations.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from zerver.lib.actions import check_send_message
|
||||||
|
from zerver.lib.response import json_success, json_error
|
||||||
|
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
|
||||||
|
from zerver.lib.validator import check_dict, check_string
|
||||||
|
from zerver.models import Client, UserProfile, MAX_SUBJECT_LENGTH
|
||||||
|
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from typing import Dict, Any, Iterable, Optional, Text
|
||||||
|
|
||||||
|
@api_key_only_webhook_view('Splunk')
|
||||||
|
@has_request_variables
|
||||||
|
def api_splunk_webhook(request, user_profile, client,
|
||||||
|
payload=REQ(argument_type='body'), stream=REQ(default='splunk'),
|
||||||
|
topic=REQ(default=None)):
|
||||||
|
# type: (HttpRequest, UserProfile, Client, Dict[str, Any], Text, Optional[Text]) -> HttpResponse
|
||||||
|
|
||||||
|
# use default values if expected data is not provided
|
||||||
|
search_name = payload.get('search_name', 'Missing search_name')
|
||||||
|
results_link = payload.get('results_link', 'Missing results_link')
|
||||||
|
host = payload.get('result', {}).get('host', 'Missing host')
|
||||||
|
source = payload.get('result', {}).get('source', 'Missing source')
|
||||||
|
raw = payload.get('result', {}).get('_raw', 'Missing _raw')
|
||||||
|
|
||||||
|
# if no topic provided, use search name but truncate if too long
|
||||||
|
if topic is None:
|
||||||
|
if len(search_name) >= MAX_SUBJECT_LENGTH:
|
||||||
|
topic = "{}...".format(search_name[:(MAX_SUBJECT_LENGTH - 3)])
|
||||||
|
else:
|
||||||
|
topic = search_name
|
||||||
|
|
||||||
|
# construct the message body
|
||||||
|
body = "Splunk alert from saved search"
|
||||||
|
body_template = ('\n[{search}]({link})\nhost: {host}'
|
||||||
|
'\nsource: {source}\n\nraw: {raw}')
|
||||||
|
body += body_template.format(search = search_name, link = results_link,
|
||||||
|
host = host, source = source, raw = raw)
|
||||||
|
|
||||||
|
# send the message
|
||||||
|
check_send_message(user_profile, client, 'stream', [stream], topic, body)
|
||||||
|
|
||||||
|
return json_success()
|
||||||
Reference in New Issue
Block a user