Splunk – Posting to Microsoft Teams via Webhooks

Using either the default webhook action or the Teams-specific webhook, Splunk searches can post data into Microsoft Teams. First, you need to get a webhook URL for your Teams channel. On the hamburger menu next to the channel, select “Connectors”. Select Webhook, provide a name for the webhook, and copy the webhook URL.

If you intend to use the generic webhook app, there is no need to install the Teams-specific one. The Teams-specific app gives you prettier output & a “view in splunk” button. Download the app tgz. To install the app, go into “Manage Apps” and select “Install app from file”.

Click ‘Browse…’ and find the tgz you downloaded. Click ‘Upload’ to install the app to Splunk.

Now create a search for which you want to post data into your Teams channel. Click “Save As” and select “Alert”

Provide a title for the alert — you can use real-time or scheduled alerts. Once you’ve got the alert sorted, select “Add Actions” and select the Teams webhook action (or the generic webhook action if you intend to use that one). Paste in the URL from your Teams channel webhook and click “Save”.

You”ll see a confirmation that the alert has been saved. Close this.

Now you would think you’d be ready to use it … but wait. Neither one works out of the box. In the Splunk log, you see error 400 “Bad data” reported.

For the default webhook app, edit the Python script (/opt/splunk/etc/apps/alert_webhook/bin/webhook.py in my case). Find the section where the JSON body is built. Teams requires a summary or title within the POST data. I just added a static summary, but you could do something fancier.

        body = OrderedDict(
            sid=settings.get('sid'),
            summary='LJRWebhook',
            search_name=settings.get('search_name'),
            app=settings.get('app'),
            owner=settings.get('owner'),
            results_link=settings.get('results_link'),
            result=settings.get('result')

For the Teams-specific webhook, edit the Python script (/opt/splunk/etc/apps/alert_msteams/bin/teams.py in my case) and find the section where the facts list is populated. There’s too much data being sent through. There’s probably a way to filter it out in Splunk, but I don’t know how 🙂

The right way to do it is select the most important items from settings.get(‘result’).items that you want to be displayed within Teams and populate facts with those elements. I used a new list, strWantedKeys, to determine which keys should be added to the facts list. The quick/ugly way is to just take the first n items from the result items (settings.get(‘results’).items()[:7] gets seven … 8 produced a ‘bad payload received by generic incoming webhook’ error from Teams.

try:
settings = json.loads(sys.stdin.read())
print >> sys.stderr, "DEBUG Settings: %s" % settings
url = settings['configuration'].get('url')
facts = []
strWantedKeys = ['sourcetype', '_raw', 'host', 'source']
for key,value in settings.get('result').items():
if key in strWantedKeys:
facts.append({"name":key, "value":value})
body = OrderedDict(

For reference, the original facts list was:

    "facts": [{
        "name": "index",
        "value": "history"
    }, {
        "name": "_raw",
        "value": "Test push to teams 555"
    }, {
        "name": "_eventtype_color",
        "value": ""
    }, {
        "name": "host",
        "value": "10.10.15.134:8088"
    }, {
        "name": "source",
        "value": "http:Sendmail testing"
    }, {
        "name": "_si",
        "value": ["49cgc3e5e52e", "history"]
    }, {
        "name": "sourcetype",
        "value": "mysourcetype"
    }, {
        "name": "_indextime",
        "value": "1544554125"
    }, {
        "name": "punct",
        "value": "___"
    }, {
        "name": "linecount",
        "value": ""
    }, {
        "name": "_time",
        "value": "1544554125"
    }, {
        "name": "eventtype",
        "value": ""
    }, {
        "name": "_sourcetype",
        "value": "mysourcetype"
    }, {
        "name": "_kv",
        "value": "1"
    }, {
        "name": "_serial",
        "value": "15"
    }, {
        "name": "_confstr",
        "value": "source::http:Sendmail testing|host::10.10.15.134:8088|mysourcetype"
    }, {
        "name": "splunk_server",
        "value": ""
    }]

Now generate a message that matches your search — you’ll see a post created in your Teams channel.

2 comments

  1. Gee says:

    in Splunk, you can use a “table” search command to filter down to a specific list of fields, e.g.
    (index=main OR index=summary) sourcetype=*mail*
    | table source host sourcetype _raw

Leave a Reply

Your email address will not be published. Required fields are marked *