Microsoft Teams via Webhook
Integration for sending notifications to a Microsoft Teams channel via a workflow of type `Post to a channel when a webhook request is received`.
Messaging and Conferencing · Microsoft Teams
Details
| ID | Microsoft Teams via Webhook |
|---|---|
| Provider | Microsoft |
| Category | Messaging and Conferencing |
| From Version | 6.2.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix Cortex Cloud Cloud Runtime Security Cloud Posture Security XSIAM EDR |
README
Integration for sending notifications to a Microsoft Teams channel via workflow.
This integration was integrated and tested with version 6.8 of Microsoft Teams via Webhook
Configure Microsoft Teams via Webhook in Cortex
| Parameter | Description | Required |
|---|---|---|
| Microsoft workflow URL | The workflow URL in the Teams Channel | True |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
ms-teams-message
Send a message to Microsoft Teams via Incoming Webhook.
Base Command
ms-teams-message
Input
| Argument Name | Description | Required |
|---|---|---|
| message | The message to send. For example: “This is a message from Cortex XSOAR”. To use a newline use \n\n or \r\r. Default is None. | Optional |
| team_webhook | The alternative webhook for a different team. If not defined, the integration’s default webhook is used. | Optional |
| alternative_url | The alternative URL to send in place of the link to the Cortex XSOAR Investigation. | Optional |
| url_title | The title for the link. Default is Cortex XSOAR URL. | Optional |
| adaptive_cards_format | Should the adaptive card format be used or a single text message. Possible values are: true, false. Default is True. | Optional |
| overwrite_adaptive_card_json | JSON object used to overwrite the default adaptive card JSON. | Optional |
Context Output
There is no context output for this command.
Troubleshooting
By default the message is being sent with a message template: X Used a Workflow template to send this card.
In order to eliminate this line you can use the following approach:
- Navigate to Microsoft’s Power Automate portal and sign into your Microsoft Teams account where you’ve previously set up the Flow.
- Click My flows from the left side menu.
- Click the newly created Flow to open its details page.
- On the Flow’s details page, click Save As.
- Give your new Flow a name and click **Save””.
- Navigate back to My flows from the left side menu.
- Find the copy Flow and click its name to access its details page.
- On the Flow’s details page, click Turn On.
- In order to find the new URL link, navigate to the Edit tab on the Flow’s details page.
- Click the action task and copy the HTTP URL.
- Configure an instance of the integration and add the copied Workflow URL for the Teams channel.
Configuration parameters
webhookurl— Microsoft workflow URL (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (1)
-
ms-teams-messageSend a message to Microsoft Teams via Incoming Webhook.
from unittest.mock import patch import pytest from pytest_mock import MockerFixture from MicrosoftTeamsWebhook import Client, send_teams_message_command, create_teams_message from requests_mock import Mocker WEBHOOK = "https://readywebookone" MESSAGE = "Hello from XSOAR" TITLE = "Cortex XSOAR URL" SERVERURLS = {"investigation": "https://readyxsoarone:443/#/Details/8675309/"} fake_client = Client(base_url=WEBHOOK, verify=True, proxy=False, is_workflow=False) def test_create_teams_message_adaptive_cards(): message = create_teams_message(MESSAGE, TITLE, SERVERURLS["investigation"], True) assert message assert message["attachments"][0]["content"]["body"][1]["text"] == MESSAGE assert message["attachments"][0]["content"]["actions"][0]["title"] == TITLE assert message["attachments"][0]["content"]["actions"][0]["url"] == SERVERURLS["investigation"] def test_create_teams_message(): message = create_teams_message(MESSAGE, TITLE, SERVERURLS["investigation"], is_workflow=False) assert message assert message["sections"][0]["activitySubtitle"] == MESSAGE assert message["potentialAction"][0]["name"] == TITLE assert message["potentialAction"][0]["targets"][0]["uri"] == SERVERURLS["investigation"] def test_send_teams_message_command(requests_mock: Mocker): requests_mock.post(WEBHOOK, status_code=200, json={}) res = send_teams_message_command(fake_client, MESSAGE, TITLE, SERVERURLS["investigation"]) assert res.readable_output == "Message sent successfully" def test_send_teams_message_command_with_adaptivecards(requests_mock: Mocker): requests_mock.post(WEBHOOK, status_code=200, json={}) res = send_teams_message_command(fake_client, MESSAGE, TITLE, SERVERURLS["investigation"], True) assert res.readable_output == "Message sent successfully" def test_send_teams_message_command_with_adaptivecards_overwrite(requests_mock: Mocker): requests_mock.post(WEBHOOK, status_code=200, json={}) res = send_teams_message_command(fake_client, MESSAGE, TITLE, SERVERURLS["investigation"], True, {"Hello": "World"}) assert res.readable_output == "Message sent successfully" def test_test_module(requests_mock: Mocker): from MicrosoftTeamsWebhook import test_module requests_mock.post(WEBHOOK, status_code=200, json={}) res = test_module(fake_client, "fake") assert res == "ok" workflow_client = Client(base_url=WEBHOOK, verify=True, proxy=False, is_workflow=True) def test_create_teams_message_adaptive_cards_is_workflow(): """ Given: - The command arguments with is_workflow = true. When: - Executing the create_teams_message function. Then: - Verify request message- should use the full adaptive card template. """ message = create_teams_message(MESSAGE, TITLE, SERVERURLS["investigation"], True, True) assert message assert message["attachments"][0]["content"]["body"][1]["text"] == MESSAGE assert message["attachments"][0]["content"]["actions"][0]["title"] == TITLE assert message["attachments"][0]["content"]["actions"][0]["url"] == SERVERURLS["investigation"] def test_create_teams_message_with_newlines(): """ Given: - Message with newlines characters with multi backslash. When: - Executing the create_teams_message function. Then: - Verify request message with only one backslash for newlines. """ message = create_teams_message("Hello from \\n\\rXSOAR", TITLE, SERVERURLS["investigation"], True, False) assert message["attachments"][0]["content"]["body"][1]["text"] == "Hello from \n\rXSOAR" def test_create_teams_message_is_workflow(): """ Given: - The command arguments with is_workflow = true. When: - Executing the create_teams_message function. Then: - Verify request message- should use the only text template. """ message = create_teams_message(MESSAGE, TITLE, SERVERURLS["investigation"], is_workflow=True) assert message assert message["attachments"][0]["content"]["body"][0]["text"] == MESSAGE assert message["attachments"][0].get("content", {}).get("actions") is None def test_send_teams_message_command_is_workflow(requests_mock: Mocker): """ Given: - The command arguments with is_workflow = true. When: - Executing the send_teams_message_command command. Then: - Verify when status is 202 we receive `Message sent successfully`. """ requests_mock.post(WEBHOOK, status_code=202, json={}) res = send_teams_message_command(workflow_client, MESSAGE, TITLE, SERVERURLS["investigation"]) assert res.readable_output == "Message sent successfully" def test_send_teams_message_command_with_full_adaptivecards_is_workflow(requests_mock: Mocker): """ Given: - The command arguments with is_workflow = true. When: - Executing the send_teams_message_command command. Then: - Verify when status is 202 we receive `Message sent successfully`. """ requests_mock.post(WEBHOOK, status_code=202, json={}) res = send_teams_message_command(workflow_client, MESSAGE, TITLE, SERVERURLS["investigation"], True) assert res.readable_output == "Message sent successfully" @pytest.mark.parametrize( "client,messagecard, adaptive_cards_format, expected_full_url", [ (fake_client, {"type": "MessageCard", "text": "Hello World"}, False, None), (fake_client, {"type": "AdaptiveCard", "text": "Hello Adaptive Card"}, True, "https://example.com/webhook"), (workflow_client, {"type": "AdaptiveCard", "text": "Hello Workflow Card"}, False, "https://example.com/webhook"), ], ) @patch("MicrosoftTeamsWebhook.demisto.info") def test_send_teams_message( mock_demisto_info, client: Client, messagecard: dict, adaptive_cards_format: bool, expected_full_url: str | None, mocker: MockerFixture, ): sender = client http_request = mocker.patch.object(client, "_http_request") http_request.return_value = "OK" sender.send_teams_message(messagecard, adaptive_cards_format) if expected_full_url: http_request.assert_called_once_with( method="POST", json_data=messagecard, raise_on_status=True, resp_type="text", full_url=sender.base_url ) else: http_request.assert_called_once_with(method="POST", json_data=messagecard, raise_on_status=True, resp_type="text") mock_demisto_info.assert_called_once_with("completed post of message. response text: OK")