Microsoft Teams¶
Table of Contents¶
Release Notes¶
Version |
Date |
Notes |
---|---|---|
3.0.0 |
08/2024 |
Added Approval Request process and ability to work with MS Teams Workflows. |
2.1.0 |
05/2023 |
Add playbooks and removed workflows |
2.0.1 |
12/2022 |
Bug fix in workflows for MS Teams: Enable Teams for Groups and MS Teams: Read messages |
2.0.0 |
12/2022 |
Added support for creating and deleting MS Groups, Teams and Channels |
1.0.0 |
10/2019 |
Post Incident/task information to MS Teams |
3.0.0 Changes¶
In v3.0, an approval request process has been added to make requests for process changes. Added is a datatable to track approval request with a poller to review changes in MS Teams based on approval or rejection replies. See V3.0 Changes for poller for additional changes needed to the app.config file to enable this capability. –> v3.0 supports MS Teams Workflows and Adaptive Cards. See the section Setting up Workflows for more information needed to configure this capability.
2.1.0 Changes¶
In v2.1, the existing rules and workflows have been replaced with playbooks. This change is made to support the ongoing, newer capabilities of playbooks. Each playbook has the same functionality as the previous, corresponding rule/workflow.
If upgrading from a previous release, you’ll notice that the previous release’s rules/workflows remain in place. Both sets of rules and playbooks are active. For manual actions, playbooks have the same name as it’s corresponding rule, but with “(PB)” added at the end. For automatic actions, the playbooks will be disabled by default.
You can continue to use the rules/workflows. But migrating to playbooks provides greater functionality along with future app enhancements and bug fixes.
Overview¶
This IBM Security QRadar SOAR application extends the meeting and collaboration functionality of Microsoft Teams. It includes the ability to create MS Teams Groups, Teams and Channels. Functionality also exists to post SOAR Incident or task information to a MS Teams Channel.
Microsoft 365 Groups are created with resources that members of the group share, including:
Outlook conversations
Outlook calendar
SharePoint files
OneNote notebook
SharePoint team site
Planner plans
Intune device management
Key Features¶
Create or delete Groups, Channels, and Teams, as well as archive or un-archive Teams. Incident and task members can be assigned to a Team.
It is now possible to create Groups, Teams, and Channels with members who are not a part of an incident or task but who have a functioning MS account that is a part of the same organization.
Post information about the Incident or task directly to a MS Channel.
Example rules/workflows are included that perform the aforementioned operations and store related information as a incident or a task note.
Requirements¶
This app supports the IBM Security QRadar SOAR Platform and the IBM Security QRadar SOAR for IBM Cloud Pak for Security.
SOAR platform¶
The SOAR platform supports two app deployment mechanisms, App Host and integration server.
If deploying to a SOAR platform with an App Host, the requirements are:
SOAR platform >=
51.0.0
.The app is in a container-based format (available from the AppExchange as a
zip
file).
If deploying to a SOAR platform with an integration server, the requirements are:
SOAR platform >=
51.0.0
.The app is in the older integration format (available from the AppExchange as a
zip
file which contains atar.gz
file).Integration server is running
resilient_circuits>=45.0.0
.If using an API key account, make sure the account provides the following minimum permissions:
Name
Permissions
Org Data
Read
Function
Read
Incident
Read, Write
Incident Private Tasks
Read
Group
Read
Users
Read
The following SOAR platform guides provide additional information:
App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
Integration Server Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
System Administrator Guide: provides the procedure to install, configure and deploy apps.
The above guides are available on the IBM Documentation website at ibm.biz/soar-docs. On this web page, select your SOAR platform version. On the follow-on page, you can find the App Host Deployment Guide or Integration Server Guide by expanding Apps in the Table of Contents pane. The System Administrator Guide is available by expanding System Administrator.
Cloud Pak for Security¶
If you are deploying to IBM Cloud Pak for Security, the requirements are:
IBM Cloud Pak for Security >= 1.10.
Cloud Pak is configured with an App Host.
The app is in a container-based format (available from the AppExchange as a
zip
file).
The following Cloud Pak guides provide additional information:
App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings. From the Table of Contents, select Case Management and Orchestration & Automation > Orchestration and Automation Apps.
System Administrator Guide: provides information to install, configure, and deploy apps. From the IBM Cloud Pak for Security IBM Documentation table of contents, select Case Management and Orchestration & Automation > System administrator.
These guides are available on the IBM Documentation website at ibm.biz/cp4s-docs. From this web page, select your IBM Cloud Pak for Security version. From the version-specific IBM Documentation page, select Case Management and Orchestration & Automation.
Proxy Server¶
The app does support a proxy server.
Python Environment¶
Both Python 3.9 and Python 3.11 are supported. Additional package dependencies may exist for each of these packages:
msal ~= 1.30
pymsteams ~= 0.2.3
resilient_circuits>=50.0.0
Endpoint Developed With MS Teams¶
This app has been implemented using:
Product Name |
API URL |
API Version |
---|---|---|
Microsoft Graph REST API |
|
V1.0 |
Installation¶
To install or uninstall an App or Integration on the SOAR platform, see the documentation at ibm.biz/soar-docs.
To install or uninstall an App on IBM Cloud Pak for Security, see the documentation at ibm.biz/cp4s-docs and follow the instructions above to navigate to Orchestration and Automation.
Endpoint Configuration¶
This application needs an access token from the Microsoft identity platform for use with Microsoft Graph APIs. The access token includes details about the application and the permission it has to use the Microsoft Graph resources and APIs. The app needs to be registered with the Microsoft identity platform and given permission to access the required Microsoft Graph resources by a user or an administrator in order to obtain an access token.
Register a new application using the Azure portal¶
The application must be registered with the identity provider for the identity provider to be aware that a specific app is attempting to access user information. The configuration necessary for the application to interface with the Microsoft identity platform is then made available when it registers with Microsoft Entra ID (formally Azure AD). You can learn more about this at learn.microsoft.com/application-model
Sign in to the Azure portal using either an enterprise account.
If your account gives you access to more than one tenant, select your account in the top right corner, and set your portal session to the Azure AD tenant that you want.
In the left-hand navigation pane, select the
Microsoft Entra ID
, and then selectApp registrations
>New registration
.When the Register an application page appears, enter your application’s registration information:
Name
- Enter a meaningful application name that will be displayed to users of the app.Supported account types
- Select which accounts you would like your application to support.Redirect URI
- Enter the redirect URI (or reply URL) for this application, i.e :https://localhost:8080/callback
Note this information as this would be required later while setting up the application in the SOAR platform.
When finished, select Register.
In the left-hand navigation pane under the
Manage
section, selectAuthentication
.Select
Yes
forEnable the following mobile and desktop flows
then clickSave
.
API Permissions¶
The application requires admins consent to access a protected resource, such as user information and Team settings. Microsoft Graph exposes certain predetermined APIs and only accepts requests made to them. These predetermined APIs or permissions can be added to individual applications thereby limiting them to only make controlled changes to the objects they are exposed to. In this case, we require permission to operate on Groups, Teams, and to read User information. You can learn more about this concept at learn.microsoft.com/scopes-oidc.
This application requires two different types of permissions to access the required Graph Objects:
Application permission
Delegated permission (Optional)
Feature |
Permission Type |
---|---|
Archive Team |
|
Create Channel |
|
Create Group |
|
Create Team |
|
Delete Channel |
|
Delete Group |
|
Enable Teams for Group |
|
Post Incident Information |
|
Read Channel Messages |
|
Application Permission¶
Application permissions, also called app roles, allow the app to access data on its own, without a signed-in user. In this access scenario, the application can interact with data on its own, without a signed in user. App-only access is used in scenarios such as automation, and is mostly used by apps that run as background services or daemons. It’s suitable when it’s undesirable to have a user signed in, or when the data required can’t be scoped to a single user.
Delegated Permission¶
This type of permission is optional and is only required for the Read Channel messages feature. If you wish to use the application without this feature (read channel messages), you can do so by leaving out the delegated permission setup process and following the remaining steps. Delegated permissions, also called scopes, allow the application to act on behalf of the signed-in user. In this access scenario, the user signs in on behalf of the application and provides it with the required permissions to call the Microsoft Graph API. Both the client and the user must be authorized to make the request. The Graph API’s read message method is one of Microsoft’s protected APIs since it has access to sensitive data. The user must grant this application permission to access their data in order for this application to function. This means that only the resources to which the user has access, such as channels and teams, will be available to this application.
Setting up API Permissions (Both Permissions)¶
In the left-hand navigation pane under the
Manage
section selectAPI Permission
.Click
Add a permission
. On the Request API permission screen, selectMicrosoft Graph
.Select the
Application permissions
option and search for all relevant permissions and add them as shown below.An admin account is required to
Grant admin consent
, to enable these permissions.
List of required permissions¶
Category |
API/Permission |
Permission Type |
Description |
---|---|---|---|
Group |
|
Application |
Create groups |
Group |
|
Application |
Read and write all groups |
GroupMember |
|
Application |
Read and write all group memberships |
Team |
|
Application |
Create teams |
Team |
|
Application |
Get a list of all teams |
TeamMember |
|
Application |
Add and remove members from all teams |
TeamMember |
|
Application |
Add and remove members with non-owner role |
TeamSettings |
|
Application |
Read and change all teams’ settings |
User |
|
Application |
Read all users’ full profiles |
ChannelMessage |
|
Application |
Read all messages |
ChannelMessage |
|
Delegated |
Read and write user channel messages |
ChannelMessage |
|
Delegated |
Send channel messages |
offline_access |
|
Delegated |
Maintain access to data you have given it access to |
Create a client Secret Value (Both Permissions)¶
In the left-hand navigation pane under the
Manage
section, selectCertificate and secrets
.Click on the
New client secret
button.Enter a name for the client secret and click on the
Add
button.Note this information as this would be required later while setting up the application in the SOAR platform.
Setting up Incoming Webhooks (Both Permissions)¶
The SOAR Platform can share content in Microsoft channels using an incoming webhook. The webhooks are utilized as tracking and notifying mechanisms. The webhooks offer a specific URL that can be used to transmit a JSON payload along with a card-format message. To configure webhooks for a channel, please refer to this documentation Create Incoming Webhooks.
Note: Webhooks are now replaced by MS Teams Workflows. Refer to MS Teams Workflows on how to start using this new capability.
Setting up Delegated permissions (Delegated permissions)¶
This setup process is to provide the application with delegated permissions which is required only for Read channel message feature. If you wish to use the application without this feature, you can do so by skipping this process.
To provide the application with the necessary permission, the OAuth Utilities Documentation is to be used.
This tool provides the user with means to login on behalf of the application and provide the application with the required permissions to act on behalf of the user.
The application_id, directory_id and secret_value are used to generate a unique refresh_token, which is later used in the app.conf file.
There are several ways to generate this Refresh token using the OAuth Utilities tool, please refer to the documentation OAuth Utilities Documentation
Once such method would be using the CLI. A sample command has been provided below:
oauth-utils oauth2_generate_refresh_token \
-tu https://login.microsoftonline.com/<DIRECTORY_ID>/oauth2/v2.0/token \
-au https://login.microsoftonline.com/<DIRECTORY_ID>/oauth2/v2.0/authorize \
-ci <APPLICATION_ID> \
-cs <SECRET_VALUE> \
-sc "ChannelMessage.Send ChannelMessage.Read.All offline_access"
Upon successfully completing this process, you will be presented with a refresh_token. Note this information as this is required later while setting up the application in the SOAR platform.
App Configuration (Both Permissions)¶
The following table provides the settings you need to configure the app. These settings are made in the app.config file. These values are used by the SOAR platform to establish a secure connection with the Microsoft Endpoint. See the documentation discussed in the Endpoint Configuration section for the procedure. If you have successfully configured that endpoint, you can find these values:
Azure portal -> App registration -> (Your application)
Config |
Required |
Example |
Description |
---|---|---|---|
application_id |
Yes |
18d10049-72e3-4652-ac9f-d9b13f24303c |
Overview -> |
directory_id |
Yes |
1d8a5928-8678-408e-ab06-50ca7e01766a |
Overview -> |
secret_value |
Yes |
oCN****************** |
Certificate & secrets -> |
refresh_token |
Optional |
eyxn****************** |
Required only for delegated permissions |
<channel_name> |
Optional |
****.webhook.office.com/webhookb2/ |
Webhook URL for a channel |
selftest |
Optional |
https://teams.microsoft.com/l/channel/xxx |
Webhook URL for channel connectors to test posting of messages. This capability is deprecated and selftest_workflows should be used starting with V3.0 |
selftest_workflows |
Optional |
https://azure.com/workflows/xxx |
Webhook URL for Teams Workflows to test posting of messages. |
* |
Optional |
https://azure.com/workflows/xxx |
Additional webhook URLs. Reference the |
MS Teams Workflows¶
In V3.0, messages can be sent via the MS Teams Workflows capability. Although a powerful way to set up complex capabilities, the basic enablement can be performed via these steps:
Within the MS Teams app (either Windows or Mac), select the Workflows app
Add a workflow for
Post to a channel when a webhook request is received
At the minimum, the workflow will have steps to send Adaptive Cards to a channel
The webhook request step contains the URL required to send Adaptive Cards to a teams channel. Copy this value and add it your app.config settings using a label of your choosing. This label will then be referred to in any message sent to the MS Teams channel via this Workflow.
Function - MS Teams Post Message for Workflows¶
Post a message to a Microsoft Teams channel intended for Workflows
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Incident id from which artifacts are to be fetched |
|
|
No |
|
- |
|
|
Yes |
|
Lookup value to channel to post a message |
|
|
Yes |
|
string-encoded json of teams conversation message: See [Adaptive Cards]](https://adaptivecards.io/) |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
'version': 2.0,
'success': True,
'reason': None,
'content': {'status_code': 202},
'inputs': { ... }
}
Example Function Input Script:
import json
import datetime
ADAPTIVE_CARD_TYPE = "AdaptiveCard"
ADAPTIVE_CARD_VERSION = "1.4"
def create_textblock(text,
style="Default",
font_type="Default",
font_size="Default",
font_weight="Default",
color="Default",
is_visible=True):
return {
"type": "TextBlock",
"text": text,
"wrap": True,
"weight": font_weight,
"size": font_size,
"color": color,
"style": style,
"isVisible": is_visible
}
def create_factset(separator=False, facts=[], is_visible=True):
return {
"type": "FactSet",
"facts": facts,
"separator": separator,
"isVisible": is_visible
}
def create_fact(title, value):
return {
"title": title,
"value": value
}
# S T A R T
body = [
create_textblock(f"SOAR Incident {incident.id}", font_weight="bolder", color="Attention"),
create_factset(facts=[
create_fact("Title", incident.name),
create_fact("Description", incident.description.content.replace('"', '\\"') if incident.description else "-"),
create_fact("Owner", incident.owner_id),
create_fact("Types", ", ".join(str(x) for x in incident.incident_type_ids)),
create_fact("NIST Attack Vectors", ", ".join(str(x) for x in incident.nist_attack_vectors)),
create_fact("Create Date", datetime.datetime.fromtimestamp(incident.create_date/1000).strftime('%c')),
create_fact("Date Occurred", datetime.datetime.fromtimestamp(incident.start_date/1000).strftime('%c') if incident.start_date else "-"),
create_fact("Discovered Date", datetime.datetime.fromtimestamp(incident.discovered_date/1000).strftime('%c')),
create_fact("Confirmed", incident.confirmed),
create_fact("Severity", incident.severity_code)
])
]
if playbook.inputs.teams_additional_comments:
body.append(create_textblock(playbook.inputs.teams_additional_comments.content))
adaptive_card = {
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": ADAPTIVE_CARD_TYPE,
"version": ADAPTIVE_CARD_VERSION,
"body": body,
"actions": []
}
}
inputs.incident_id = incident.id
inputs.teams_payload = json.dumps(adaptive_card)
inputs.teams_channel = playbook.inputs.teams_channel
Example Function Post Process Script:
import time
results = playbook.functions.results.ms_teams_post_result
if results["success"]:
#
row = incident.addRow("msteams_approval_process")
row["date"] = int(time.time()*1000)
row["status"] = "Pending"
row["channel"] = playbook.inputs.teams_channel
row["expiration"] = playbook.inputs.approval_expiration
row["message"] =playbook.inputs.approval_message
row["soar_message_id"] = playbook.properties.soar_message_id.message_id
row["group"] = playbook.inputs.teams_group
row["task_id"] = task.id
row["task_name"] = task.name
else:
incident.addNote(f"MS Teams approval post to channel {playbook.inputs.teams_channel} failed with: {results.reason}")
Function - MS Teams: Archive Team¶
This function allows for archiving or unarchiving a Microsoft Team. The archive_operation
input parameter specifies if the team is to be archived or unarchived. Archiving does not delete the MS Team. To identify the team for archival or unarchival, one of the following inputs can be used:
ms_groupteam_id
ms_group_mail_nickname
ms_groupteam_name
Note: When multiple options are provided to locate the Graph object (Group or a Team), the ms_group_mail_nickname
parameter will take precedence over ms_groupteam_name
, and the ms_groupteam_id
parameter will take precedence over the other two options.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Specify the operation to be performed |
|
|
No |
|
Unique value, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Unique id assigned to a MS Group or Team while being created |
|
|
No |
|
Name assigned to the MS Group or Team while being created |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups/$entity",
"id": "87fd1ea0-6a3f-4078-b271-e4f8e6f8469e",
"deletedDateTime": null,
"classification": null,
"createdDateTime": "2023-05-15T17:39:58Z",
"creationOptions": [
"Team",
"ExchangeProvisioningFlags:3552"
],
"description": "task testing",
"displayName": "task testing",
"expirationDateTime": null,
"groupTypes": [
"Unified"
],
"isAssignableToRole": null,
"mail": "tasktesting@example.com",
"mailEnabled": true,
"mailNickname": "tasktesting",
"membershipRule": null,
"membershipRuleProcessingState": null,
"onPremisesDomainName": null,
"onPremisesLastSyncDateTime": null,
"onPremisesNetBiosName": null,
"onPremisesSamAccountName": null,
"onPremisesSecurityIdentifier": null,
"onPremisesSyncEnabled": null,
"preferredDataLocation": null,
"preferredLanguage": null,
"proxyAddresses": [
"SMTP:tasktesting@example.com"
],
"renewedDateTime": "2023-05-15T17:39:58Z",
"resourceBehaviorOptions": [
"HideGroupInOutlook",
"SubscribeMembersToCalendarEventsDisabled",
"WelcomeEmailDisabled"
],
"resourceProvisioningOptions": [
"Team"
],
"securityEnabled": false,
"securityIdentifier": "S-1-12-1-2281512608-1081633343-4175720882-2655451366",
"theme": null,
"visibility": "Private",
"onPremisesProvisioningErrors": [],
"status_code": 200,
"message": "Successfully archived Team: task testing",
"teamsEnabled": "Archived"
},
"raw": null,
"inputs": {
"ms_groupteam_id": "87fd1ea0-6a3f-4078-b271-e4f8e6f8469e",
"archive_operation": "Archive",
"ms_group_mail_nickname": "",
"ms_groupteam_name": ""
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 2030,
"timestamp": "2023-05-15 13:47:58"
}
}
Example Pre-Process Script:
inputs.archive_operation = "Archive"
if playbook.inputs.archive_operation:
inputs.archive_operation = playbook.inputs.archive_operation
if playbook.inputs.ms_groupteam_id:
inputs.ms_groupteam_id = playbook.inputs.ms_groupteam_id
elif playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
elif playbook.inputs.ms_groupteam_name:
inputs.ms_groupteam_name = playbook.inputs.ms_groupteam_name
else:
helper.fail("No input was provided")
Example Post-Process Script:
results = playbook.functions.results.archive_results
content = results.get("content")
if not results.get("success"):
text = "Unable to archive the Microsoft Team"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f"""<b>Microsoft Team Details:</b><br />
<br />The Team associated with this Group has now been {content.get('teamsEnabled')}.<br />
<br />Name: {content.get('displayName')}
<br />Description: {content.get('description')}
<br />Teams Enabled: {content.get('teamsEnabled')}
<br />ID: {content.get('id')}
<br />Mail: {content.get('mail')}
<br />Visibility: {content.get('visibility')}
<br />Group Types: {content.get('groupTypes')}
<br />Created date and time: {content.get('createdDateTime')}"""
if content.get("unfoundUsers"):
text += f"<br />*Note the following users were unable to be added to the group: {content.get('unfoundUsers')}"
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Create Channel¶
This function creates a Microsoft Channel for a MS Team. A MS Team can have multiple channels.
To create a Channel for an MS Team, 3 key attributes are required, namely: teamId, displayName, and description. Out of these attributes, teamId is crucial as the MS Team must be properly identified before channel addition operation can take place. This function has the ability to find the required teamId using anyone of the below mentioned options:
ms_groupteam_id
ms_group_mail_nickname
ms_groupteam_name
Note: When multiple options are provided to locate the Graph object (Group or a Team), the ms_group_mail_nickname
parameter will take precedence over ms_groupteam_name
, and the ms_groupteam_id
parameter will take precedence over the other two parameters.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Name of the Microsoft Teams channel |
|
|
No |
|
Description for the MS Graph Object (Group / Team / Channel) that is being created |
|
|
No |
|
Unique value, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Unique id assigned to the MS Group or Team |
|
|
No |
|
Name assigned to the MS Group or Team |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams('33333-450e-46d6-9338-f7e3b66a064c')/channels/$entity",
"id": "19:c875f7333fb843aeacb01d1cbfa52ae5@thread.tacv2",
"createdDateTime": "2023-05-15T18:26:57.6422279Z",
"displayName": "test 1234",
"description": "test 1234",
"isFavoriteByDefault": false,
"email": "",
"webUrl": "https://teams.microsoft.com/l/channel/19%3ac875f7333fb843aeacb01d1cbfa52ae5%40thread.tacv2/test+1234?groupId=33333-450e-46d6-9338-f7e3b66a064c&tenantId=55555-b889-434d-802d-13b87c68047b",
"membershipType": "standard",
"status_code": 201,
"message": "Successfully created channel: test 1234"
},
"raw": null,
"inputs": {
"ms_groupteam_id": "33333-450e-46d6-9338-f7e3b66a064c",
"ms_channel_name": "test 1234",
"ms_description": "test 1234"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 4593,
"timestamp": "2023-05-15 14:26:57"
}
}
Example Pre-Process Script:
inputs.ms_channel_name = playbook.inputs.ms_channel_name if playbook.inputs.ms_channel_name else f"Incident {incident.id} {incident.name}"
if playbook.inputs.ms_description:
inputs.ms_description = playbook.inputs.ms_description
else:
description = incident.description.content if incident.description else ""
inputs.ms_description = f"Incident {incident.id}: {incident.name} {description}"
if playbook.inputs.ms_groupteam_id:
inputs.ms_groupteam_id = playbook.inputs.ms_groupteam_id
elif playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
elif playbook.inputs.ms_groupteam_name:
inputs.ms_groupteam_name = playbook.inputs.ms_groupteam_name
else:
helper.fail("No input was provided")
Example Post-Process Script:
results = playbook.functions.results.create_channel_results
content = results.get("content")
if not results.get("success"):
text = "Unable to create Microsoft Group"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f'''<a href="{content.get("webUrl")}">Click here</a>
<b>Microsoft Channel Details:</b><br />
<br />Name: {content.get("displayName")}
<br />Web URL: {url}
<br />Description: {content.get("description")}
<br />Teams Enabled: {True}
<br />ID: {content.get("id")}
<br />Mail: {content.get("email")}
<br />Membership Type: {content.get("membershipType")}'''
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Create group¶
This function creates a Microsoft Group with the ability to add multiple owners by specifying their email addresses in a comma-separated list. At least one owner must be mentioned for group creation.
The function is developed to automatically add all members of an incident or a task to the MS Group. If the function is executed from within a task, in addition to task members, all incident members can also be automatically added if that option is selected. Apart from automatic member addition, individual members can be added by directly specifying their email addresses.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
Yes |
|
Add incident or task members to Team/Group |
|
|
No |
|
Add additional Team members who are not members of this incident or task |
|
|
No |
|
Incident id of the current incident |
|
|
No |
|
Description for the MS Group |
|
|
No |
|
Unique value, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Name of the MS Group |
|
|
No |
|
A list of owners for the Group |
|
|
No |
|
Incident task id if creating a Group from a task. |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"id": "3cde21c1-7e9c-4f6d-b986-06d879c43dad",
"deletedDateTime": null,
"classification": null,
"createdDateTime": "2023-05-15T18:13:38Z",
"creationOptions": [],
"description": "test1",
"displayName": "test1",
"expirationDateTime": null,
"groupTypes": [
"Unified"
],
"isAssignableToRole": null,
"mail": "test1@example.com",
"mailEnabled": true,
"mailNickname": "test1",
"membershipRule": null,
"membershipRuleProcessingState": null,
"onPremisesDomainName": null,
"onPremisesLastSyncDateTime": null,
"onPremisesNetBiosName": null,
"onPremisesSamAccountName": null,
"onPremisesSecurityIdentifier": null,
"onPremisesSyncEnabled": null,
"preferredDataLocation": null,
"preferredLanguage": null,
"proxyAddresses": [
"SMTP:test1@example.com"
],
"renewedDateTime": "2023-05-15T18:13:38Z",
"resourceBehaviorOptions": [],
"resourceProvisioningOptions": [],
"securityEnabled": false,
"securityIdentifier": "S-1-12-1-1021190593-1332575900-3624306361-2906506361",
"theme": null,
"visibility": "Private",
"onPremisesProvisioningErrors": [],
"teamsEnabled": false,
"unfoundUsers": []
},
"raw": null,
"inputs": {
"incident_id": 2122,
"additional_members": "",
"ms_owners_list": "markscherfling@example.com",
"ms_group_name": "test1",
"ms_group_mail_nickname": "test1",
"add_members_from": "None",
"task_id": null,
"ms_description": "test1"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 1560,
"timestamp": "2023-05-15 14:13:39"
}
}
Example Pre-Process Script:
if task:
inputs.task_id = task.id
inputs.incident_id = str(incident.id)
inputs.ms_group_name = f"Incident {incident.id}: {incident.name}" if playbook.inputs.ms_group_name is None else playbook.inputs.ms_group_name
if playbook.inputs.ms_owners_list:
inputs.ms_owners_list = playbook.inputs.ms_owners_list
if playbook.inputs.add_members_incident:
_value = playbook.inputs.add_members_incident.lower().strip()
if _value == "all incident members":
inputs.add_members_from = "Incident"
else:
inputs.add_members_from = "None"
if playbook.inputs.additional_members.content:
inputs.additional_members = playbook.inputs.additional_members.content
if playbook.inputs.ms_description:
inputs.ms_description = playbook.inputs.ms_description
else:
description = incident.description.content if incident.description else ""
inputs.ms_description = f"Incident {incident.id}: {incident.name} {description}"
if playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
Example Post-Process Script:
results = playbook.functions.results.create_group_results
content = results.get("content")
if not results.get("success"):
text = "Unable to create Microsoft Group"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f'''<b>Microsoft Group Details:</b><br />
<br />Name: {content.get("displayName")}
<br />Description: {content.get("description")}
<br />Teams Enabled: {content.get("teamsEnabled")}
<br />ID: {content.get("id")}
<br />Mail: {content.get("mail")}
<br />Visibility: {content.get("visibility")}
<br />Group Types: {content.get("groupTypes")}
<br />Created date and time: {content.get("createdDateTime")}'''
if content.get("unfoundUsers"):
text += f'<br />*Note the following users were unable to be added to the group: {content.get("unfoundUsers")}'
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Create team¶
This function creates a Microsoft Team with the ability to add multiple owners by specifying their email addresses in a comma-separated list. At least one owner must be mentioned for group creation.
The function is developed to automatically add all members of an incident or a task to the MS Team. If the function is executed from within a task, in addition to task members, all incident members can also be automatically added if that option is selected. Apart from automatic member addition, individual members can be added by directly specifying their email addresses.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
Yes |
|
Allows for adding incident or task members to Team |
|
|
No |
|
Add members who are not members of this incident or task |
|
|
No |
|
Incident Id associate with this workflow/playbook |
|
|
No |
|
Description for the MS Graph Team that is being created |
|
|
No |
|
A comma separated list of owners for the group or team |
|
|
No |
|
Name of the Microsoft Team |
|
|
No |
|
Incident task id if this Team is associated with a task |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups/$entity",
"id": "87fd1ea0-6a3f-4078-b271-e4f8e6f8469e",
"deletedDateTime": null,
"classification": null,
"createdDateTime": "2023-05-15T17:39:58Z",
"creationOptions": [
"Team",
"ExchangeProvisioningFlags:3552"
],
"description": "task testing",
"displayName": "task testing",
"expirationDateTime": null,
"groupTypes": [
"Unified"
],
"isAssignableToRole": null,
"mail": "tasktesting@example.com",
"mailEnabled": true,
"mailNickname": "tasktesting",
"membershipRule": null,
"membershipRuleProcessingState": null,
"onPremisesDomainName": null,
"onPremisesLastSyncDateTime": null,
"onPremisesNetBiosName": null,
"onPremisesSamAccountName": null,
"onPremisesSecurityIdentifier": null,
"onPremisesSyncEnabled": null,
"preferredDataLocation": null,
"preferredLanguage": null,
"proxyAddresses": [
"SMTP:tasktesting@example.com"
],
"renewedDateTime": "2023-05-15T17:39:58Z",
"resourceBehaviorOptions": [
"HideGroupInOutlook",
"SubscribeMembersToCalendarEventsDisabled",
"WelcomeEmailDisabled"
],
"resourceProvisioningOptions": [
"Team"
],
"securityEnabled": false,
"securityIdentifier": "S-1-12-1-2281512608-1081633343-4175720882-2655451366",
"theme": null,
"visibility": "Private",
"onPremisesProvisioningErrors": [],
"status_code": 200,
"teamsEnabled": true,
"unfoundUsers": null
},
"raw": null,
"inputs": {
"ms_team_name": "task testing",
"incident_id": 2120,
"additional_members": "",
"ms_owners_list": "markscherfling@example.com",
"add_members_from": "None",
"task_id": 126,
"ms_description": "task testing"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 50594,
"timestamp": "2023-05-15 13:40:47"
}
}
Example Pre-Process Script:
if task:
inputs.task_id = task.id
inputs.incident_id = str(incident.id)
inputs.ms_team_name = f"Incident {incident.id}: {incident.name}" if playbook.inputs.ms_team_name is None else playbook.inputs.ms_team_name
if playbook.inputs.ms_owners_list:
inputs.ms_owners_list = playbook.inputs.ms_owners_list
if playbook.inputs.add_members_incident:
_value = playbook.inputs.add_members_incident.lower().strip()
if _value == "all incident members":
inputs.add_members_from = "Incident"
else:
inputs.add_members_from = "None"
if playbook.inputs.additional_members.content:
inputs.additional_members = playbook.inputs.additional_members.content
if playbook.inputs.ms_description:
inputs.ms_description = playbook.inputs.ms_description
else:
description = incident.description.content if incident.description else ""
inputs.ms_description = f"Incident {incident.id}: {incident.name} {description}"
Example Post-Process Script:
results = playbook.functions.results.create_team
content = results.get("content")
if not results.get("success"):
text = "Unable to create Microsoft Team"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f'''<b>Microsoft Group Details:</b><br />
<br />Name: {content.get("displayName")}
<br />Description: {content.get("description")}
<br />Teams Enabled: {content.get("teamsEnabled")}
<br />ID: {content.get("id")}
<br />Mail: {content.get("mail")}
<br />Visibility: {content.get("visibility")}
<br />Group Types: {content.get("groupTypes")}
<br />Created date and time: {content.get("createdDateTime")}'''
if content.get("unfoundUsers"):
text += f'<br />*Note the following users were unable to be added to the group: {content.get("unfoundUsers")}'
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Delete Channel¶
This function deletes a MS Channel. A MS Team can be assigned to multiple channels. However, each MS Group can have only one Team. In order to delete an Channel, it’s MS Team/Group needs to be identified. To locate this team for this operation, one of the following inputs can be used:
ms_groupteam_id
ms_group_mail_nickname
ms_groupteam_name
Note: When multiple options are provided to locate the Graph object (Group or a Team), the ms_group_mail_nickname
parameter will take precedence over ms_groupteam_name
, and the ms_groupteam_id
parameter will take precedence over the other two.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Name of the Microsoft Teams channel |
|
|
No |
|
Unique nickname for a group. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Unique id assigned to a MS Group or Team while being created |
|
|
No |
|
Name assigned to the MS Group or Team while being created |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"status_code": 204,
"message": "Successfully deleted channel: Incident 2121 testing channels"
},
"raw": null,
"inputs": {
"ms_groupteam_id": "33333-450e-46d6-9338-f7e3b66a064c",
"ms_channel_name": "Incident 2121 testing channels"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 3172,
"timestamp": "2023-05-15 14:09:04"
}
}
Example Pre-Process Script:
inputs.ms_channel_name = playbook.inputs.ms_channel_name
if playbook.inputs.ms_groupteam_id:
inputs.ms_groupteam_id = playbook.inputs.ms_groupteam_id
elif playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
elif playbook.inputs.ms_groupteam_name:
inputs.ms_groupteam_name = playbook.inputs.ms_groupteam_name
else:
helper.fail("No input was provided")
Example Post-Process Script:
results = playbook.functions.results.delete_channel
content = results.get("content")
if not results.get("success"):
text = "Unable to delete Microsoft Channel"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f"""<b>Microsoft Channels:</b><br />
<br />{content.get('message')}"""
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Delete Group¶
This function deletes a MS Group. To identify this Group, one of the following inputs can be used:
ms_group_id
ms_group_mail_nickname
ms_group_name
Note: When multiple parameters are provided to locate the Graph object (Group or a Team), the ms_group_mail_nickname
parameter will take precedence over the ms_group_name
, and the ms_group_id
parameter will take precedence over the other two.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Unique id assigned to a group |
|
|
No |
|
Unique nickname, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Name of the MS Group |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"status_code": 204,
"message": "Successfully deleted Group: test1"
},
"raw": null,
"inputs": {
"ms_group_id": "3cde21c1-7e9c-4f6d-b986-06d879c43dad"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 2032,
"timestamp": "2023-05-15 14:15:02"
}
}
Example Pre-Process Script:
if playbook.inputs.ms_group_id:
inputs.ms_group_id = playbook.inputs.ms_group_id
elif playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
elif playbook.inputs.ms_group_name:
inputs.ms_group_name = playbook.inputs.ms_group_name
else:
helper.fail("Atleast one option must be specified to delete a group")
Example Post-Process Script:
results = playbook.functions.results.delete_group
content = results.get("content")
if not results.get("success"):
text = "Unable to delete Microsoft Group"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f'''<b>Microsoft Groups:</b><br />
<br />{content.get("message")}'''
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Enable Team¶
This function enables an MS Team for a MS Group. When an MS Group is created, the teams’ functionality is not enabled by default. Use this function to enable this for an MS Group that was recently created or for an existing Group.
To identify the Group, one of the following inputs can be used:
ms_group_id
ms_group_mail_nickname
ms_group_name
Note: When multiple parameters are provided to locate the Graph Group, the ms_group_mail_nickname
parameter will take precedence over ms_group_name
and the ms_group_id
parameter will take precedence over the other two.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Group Unique id |
|
|
No |
|
Unique nickname, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Name of the MS Group |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups/$entity",
"id": "3cde21c1-7e9c-4f6d-b986-06d879c43dad",
"deletedDateTime": null,
"classification": null,
"createdDateTime": "2023-05-15T18:13:38Z",
"creationOptions": [],
"description": "test1",
"displayName": "test1",
"expirationDateTime": null,
"groupTypes": [
"Unified"
],
"isAssignableToRole": null,
"mail": "test1@example.com",
"mailEnabled": true,
"mailNickname": "test1",
"membershipRule": null,
"membershipRuleProcessingState": null,
"onPremisesDomainName": null,
"onPremisesLastSyncDateTime": null,
"onPremisesNetBiosName": null,
"onPremisesSamAccountName": null,
"onPremisesSecurityIdentifier": null,
"onPremisesSyncEnabled": null,
"preferredDataLocation": null,
"preferredLanguage": null,
"proxyAddresses": [
"SMTP:test1@example.com"
],
"renewedDateTime": "2023-05-15T18:13:38Z",
"resourceBehaviorOptions": [],
"resourceProvisioningOptions": [],
"securityEnabled": false,
"securityIdentifier": "S-1-12-1-1021190593-1332575900-3624306361-2906506361",
"theme": null,
"visibility": "Private",
"onPremisesProvisioningErrors": [],
"status_code": 200,
"message": "Successfully enabled Teams for Group: test1",
"teamsEnabled": true
},
"raw": null,
"inputs": {
"ms_group_id": "3cde21c1-7e9c-4f6d-b986-06d879c43dad"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 4333,
"timestamp": "2023-05-15 14:14:23"
}
}
Example Pre-Process Script:
if playbook.inputs.ms_group_id:
inputs.ms_group_id = playbook.inputs.ms_group_id
elif playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
elif playbook.inputs.ms_group_name:
inputs.ms_group_name = playbook.inputs.ms_group_name
else:
helper.fail("No input was provided.")
Example Post-Process Script:
results = playbook.functions.results.enable_team
content = results.get("content")
if not results.get("success"):
text = "Could not enable Teams for this MS Group"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f'''<b>Microsoft Group Details:</b><br />
<br />Name: {content.get("displayName")}
<br />Description: {content.get("description")}
<br />Teams Enabled: {content.get("teamsEnabled")}
<br />ID: {content.get("id")}
<br />Mail: {content.get("mail")}
<br />Visibility: {content.get("visibility")}
<br />Group Types: {content.get("groupTypes")}
<br />Created date and time: {content.get("createdDateTime")}'''
if content.get("unfoundUsers"):
text += f'<br />*Note the following users were unable to be added to the group: {content.get("unfoundUsers")}'
note = helper.createRichText(text)
incident.addNote(note)
Function - MS Teams: Post Message¶
This application posts Incident or Task details to a MS Teams channel. The channel name, specified by the teams_channel
parameter, is used to lookup the appropriate channel webhook url maintained in app.config.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Unique id for the associated Incident |
|
|
No |
|
Unique id for a task if task information will be posted |
|
|
Yes |
|
Lookup value of channel to post a message |
|
|
Yes |
|
- |
|
|
Yes |
|
String encoded JSON including incident or task information: sections, title, text, facts |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": {
"message": "Information successfully posted in channel General"
},
"raw": null,
"inputs": {
"teams_channel": "General",
"incident_id": 2121,
"teams_mrkdown": true,
"teams_payload": "{ \"summary\": \"SOAR Incident\", \"sections\": [ \n { \"facts\": [ \n { \"name\": \"Name\", \"value\": \"testing channels\" }, \n { \"name\": \"Description\", \"value\": \"-\" }, \n { \"name\": \"Id\", \"value\": \"2121\" }, \n { \"name\": \"Owner\", \"value\": \"i@example.com\" }, \n { \"name\": \"Types\", \"value\": \"\" }, \n { \"name\": \"NIST Attack Vectors\", \"value\": \"\" }, \n { \"name\": \"Create Date\", \"value\": \"1684173230796\" }, \n { \"name\": \"Date Occurred\", \"value\": \"-\" }, \n { \"name\": \"Discovered Date\", \"value\": \"1684173210301\" }, \n { \"name\": \"Confirmed\", \"value\": \"True\" }, \n { \"name\": \"Severity\", \"value\": \"Low\" } \n ]\n }\n ] \n} \n"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 2038,
"timestamp": "2023-05-15 14:21:57"
}
}
Example Pre-Process Script:
inputs.incident_id = incident.id
"""
format of a payload. * = optional
{ "title"*: xx,
"summary": xx,
"sections": [{ "title"*: yy, "text"*: yy,
"facts"*: [{"name": zz, "value": zz}]
}]
}
"""
payload = '''{{ "summary": "SOAR Incident", "sections": [
{{ "facts": [
{{ "name": "Name", "value": "{}" }},
{{ "name": "Description", "value": "{}" }},
{{ "name": "Id", "value": "{}" }},
{{ "name": "Owner", "value": "{}" }},
{{ "name": "Types", "value": "{}" }},
{{ "name": "NIST Attack Vectors", "value": "{}" }},
{{ "name": "Create Date", "value": "{}" }},
{{ "name": "Date Occurred", "value": "{}" }},
{{ "name": "Discovered Date", "value": "{}" }},
{{ "name": "Confirmed", "value": "{}" }},
{{ "name": "Severity", "value": "{}" }}
]
}}
]
}}
'''.format(incident.name, incident.description.content.replace('"', '\\"') if incident.description else "-", incident.id,
incident.owner_id if incident.owner_id else "-",
", ".join(str(x) for x in incident.incident_type_ids), ", ".join(str(x) for x in incident.nist_attack_vectors),
incident.create_date, incident.start_date if incident.start_date else "-", incident.discovered_date,
"True" if incident.confirmed else "False",
"-" if not incident.severity_code else incident.severity_code)
inputs.teams_payload = payload
inputs.teams_channel = "General"
inputs.teams_mrkdown = True
Example Post-Process Script:
results = playbook.functions.results.post_message
content = results.get("content")
if not results.get("success"):
text = "Unable to Post message"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
text = helper.createRichText(text)
incident.addNote(text)
Function - MS Teams: Read Message¶
Read messages from a Teams Channel
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
Unique Id assigned to a channel while being created |
|
|
No |
|
Name of the Microsoft Teams channel |
|
|
No |
|
Unique value, as no two MS Objects can have the same email ID. The mail address need not include the domain suffix (i.e. @example.com) |
|
|
No |
|
Unique id assigned to a MS Group or Team while being created |
|
|
No |
|
Name of the MS Team or Group |
|
|
No |
|
Each message has a unique ID |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
"version": 2.0,
"success": true,
"reason": null,
"content": [
{
"id": "1684173756348",
"replyToId": null,
"etag": "1684173756348",
"messageType": "message",
"createdDateTime": "2023-05-15T18:02:36.348Z",
"lastModifiedDateTime": "2023-05-15T18:02:36.348Z",
"lastEditedDateTime": null,
"deletedDateTime": null,
"subject": null,
"summary": null,
"chatId": null,
"importance": "normal",
"locale": "en-us",
"webUrl": "https://teams.microsoft.com/l/message/19%3Aa62cab990d8648b6a9047787e030fa7e%40thread.tacv2/1684173756348?groupId=33333-450e-46d6-9338-f7e3b66a064c&tenantId=55555-b889-434d-802d-13b87c68047b&createdTime=1684173756348&parentMessageId=1684173756348",
"policyViolation": null,
"eventDetail": null,
"from": {
"application": null,
"device": null,
"user": {
"@odata.type": "#microsoft.graph.teamworkUserIdentity",
"id": "43dd7b73-6a70-475e-88c3-609a9f30b514",
"displayName": "Mark Scherfling",
"userIdentityType": "aadUser",
"tenantId": "55555-b889-434d-802d-13b87c68047b"
}
},
"body": {
"contentType": "text",
"content": "hello world"
},
"channelIdentity": {
"teamId": "33333-450e-46d6-9338-f7e3b66a064c",
"channelId": "19:a62cab990d8648b6a9047787e030fa7e@thread.tacv2"
},
"attachments": [],
"mentions": [],
"reactions": []
}
],
"raw": null,
"inputs": {
"ms_groupteam_id": "33333-450e-46d6-9338-f7e3b66a064c",
"ms_channel_name": "Incident 2121 testing channels"
},
"metrics": {
"version": "1.0",
"package": "fn-teams",
"package_version": "2.1.0",
"host": "local",
"execution_time_ms": 3707,
"timestamp": "2023-05-15 14:06:30"
}
}
Example Pre-Process Script:
if playbook.inputs.ms_message_id:
inputs.ms_message_id = playbook.inputs.ms_message_id
if playbook.inputs.ms_channel_id:
inputs.ms_channel_id = playbook.inputs.ms_channel_id
if playbook.inputs.ms_groupteam_id:
inputs.ms_groupteam_id = playbook.inputs.ms_groupteam_id
if playbook.inputs.ms_channel_name:
inputs.ms_channel_name = playbook.inputs.ms_channel_name
if playbook.inputs.ms_groupteam_id:
inputs.ms_groupteam_id = playbook.inputs.ms_groupteam_id
if playbook.inputs.ms_group_mail_nickname:
inputs.ms_group_mail_nickname = playbook.inputs.ms_group_mail_nickname
if playbook.inputs.ms_groupteam_name:
inputs.ms_groupteam_name = playbook.inputs.ms_groupteam_name
Example Post-Process Script:
results = playbook.functions.results.read_message
content = results.get("content", {})
if not results.get("success"):
text = "Unable to read messages from Microsoft Channel"
fail_reason = results.get("reason")
if fail_reason:
text = f"{text}:\n\tFailure reason: {fail_reason}"
else:
text = f"""<b>Microsoft Channels:</b><br />
Successfully retrieved <b>{len(content)}</b> messages <br /><br />"""
for message in content:
url = f'''<a href="{message.get("webUrl")}">Click here</a>
Message Id : {message.get("id")} <br />
Channel Id : {message.get("channelIdentity", {}).get("channelId")} <br />
Team Id : {message.get("channelIdentity", {}).get("teamId")} <br />'''
if message.get("from"):
user_messages = message.get("from", {}).get("user", {})
if user_messages:
text += f'From User : {user_messages.get("displayName")} <br />'
else:
text += f'From Application : {message.get("from", {}).get("application", {}).get("displayName")} <br />'
text += f'''Body Content : {message.get("body", {}).get("content")} <br />
Content Type : {message.get("body", {}).get("contentType")} <br />
Created Time : {message.get("createdDateTime")} <br />
Web URL : {url} <br />
<br />'''
note = helper.createRichText(text)
incident.addNote(note)
Playbooks¶
Playbook Name |
Description |
Activation Type |
Object |
Status |
Condition |
---|---|---|---|---|---|
MS Teams: Archive Team From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Archive Team (PB) |
None |
Manual |
incident |
|
|
MS Teams: Create Channel From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Create Channel (PB) |
None |
Manual |
incident |
|
|
MS Teams: Create Group From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Create Group (PB) |
None |
Manual |
incident |
|
|
MS Teams: Create Team From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Create Team (PB) |
None |
Manual |
incident |
|
|
MS Teams: Delete Channel From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Delete Channel (PB) |
None |
Manual |
incident |
|
|
MS Teams: Delete Group From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Delete Group (PB) |
None |
Manual |
incident |
|
|
MS Teams: Enable Teams for Group From Task (PB) |
None |
Manual |
task |
|
|
MS Teams: Enable Teams for Group (PB) |
None |
Manual |
incident |
|
|
MS Teams: Post Incident Information (PB) |
None |
Manual |
incident |
|
|
MS Teams: Post Message for Workflows |
Post a message to a Teams channel using the new Workflows model |
Manual |
incident |
|
|
MS Teams: Post Chat Message (using Workflows) |
incident |
|
|
||
MS Teams: Post Chat Task Message (using Workflows) |
task |
|
|
||
MS Teams: Post Task Information (PB) |
None |
Manual |
task |
|
|
MS Teams: Read Channel Messages From task (PB) |
None |
Manual |
task |
|
|
MS Teams: Read Channel Messages (PB) |
None |
Manual |
incident |
|
|
MS Teams: Send Approval Request |
Playbook to send an approval for change to a MS Teams channel. The status of the approval is tracked in the ‘MS Teams Approval Process’ datatable. |
Manual |
incident |
|
|
MS Teams: Send Approval Request for Tasks |
Playbook to send an approval for change to a MS Teams channel. The status of the approval is tracked in the ‘MS Teams Approval Process’ datatable. |
Manual |
task |
|
|
Troubleshooting & Support¶
Refer to the documentation listed in the Requirements section for troubleshooting information.
For Support¶
This is a IBM Community provided App. Please search the Community ibm.biz/soarcommunity for assistance.