MattermostV2
Mattermost is an open-source, self-hostable online chat service with file sharing, search, and integrations. It is designed as an internal chat for organizations and companies.
Messaging and Conferencing · Mattermost
Details
| ID | MattermostV2 |
|---|---|
| Provider | Mattermost Inc |
| Category | Messaging and Conferencing |
| From Version | 6.10.0 |
| Docker Image | demisto/netutils:1.0.0.10187688 |
| Supported Modules | Agentix XSIAM |
README
Mattermost is an open-source, self-hostable online chat service with file sharing, search, and integrations. It is designed as an internal chat for organizations and companies.
This integration was integrated and tested with version 4.0.0 of Mattermost API.
Some changes have been made that might affect your existing content.
If you are upgrading from a previous version of this integration, see Breaking Changes.
Configure Mattermost v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL | True | |
| Bot Access Token | The Bot Access Token to use for connection. | True |
| Personal Access Token | The Personal Access Token to use for connection. | True |
| Team Name | True | |
| Default Notifications Channel | If Notifications Channel name is not specified, will send notification to incidentNotificationChannel channel. | False |
| Enable Incident Mirroring | False | |
| Allow external users to create incidents via DM. | False | |
| Types of Notifications to Send | Notifications of type ‘externalAskSubmit’ or ‘externalFormSubmit’ are not configurable because they are required to allow Ask tasks to be sent correctly. | False |
| Long running instance. Required for investigation mirroring and direct messages. | False | |
| 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.
mattermost-get-team
Gets a team’s details.
Required Permissions
Must be authenticated and have the view_team permission.
Base Command
mattermost-get-team
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The name of the team to retrieve. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.Team.id | String | The ID of the team. |
| Mattermost.Team.create_at | Unknown | When was the team created. |
| Mattermost.Team.update_at | Unknown | When was the team updated. |
| Mattermost.Team.delete_at | Unknown | When was the team deleted. |
| Mattermost.Team.display_name | String | The display name of the team. |
| Mattermost.Team.name | String | The name of the team. |
| Mattermost.Team.description | String | The description of the team. |
| Mattermost.Team.email | String | The email of the team. |
| Mattermost.Team.type | String | The type of the team. |
| Mattermost.Team.company_name | String | The company name of the team. |
| Mattermost.Team.allowed_domains | String | The allowed domains of the team. |
| Mattermost.Team.invite_id | String | The allowed domains of the team. |
| Mattermost.Team.allow_open_invite | Unknown | Does the team allow open invites. |
| Mattermost.Team.scheme_id | String | The scheme ID of the team. |
| Mattermost.Team.policy_id | String | The policy ID of the team. |
Command example
!mattermost-get-team team_name=panw
Context Example
{
"Mattermost": {
"Team": {
"allow_open_invite": false,
"allowed_domains": "",
"cloud_limits_archived": false,
"company_name": "",
"create_at": 1696486762638,
"delete_at": 0,
"description": "",
"display_name": "PANW",
"email": "rrapoport@example.com",
"group_constrained": false,
"id": "6ie46zmi4fdqiqqe7p5gfki9hr",
"invite_id": "ocoh4fcrw7dzxgfu5bdtqpy7cr",
"name": "panw",
"policy_id": null,
"scheme_id": "",
"type": "O",
"update_at": 1696486762638
}
}
}
Human Readable Output
Team details
allow_open_invite allowed_domains cloud_limits_archived company_name create_at delete_at description display_name group_constrained id invite_id name policy_id scheme_id type update_at false false 1696486762638 0 PANW false id id panw O 1696486762638
mattermost-list-channels
Lists channels.
Required Permissions
manage_system
Base Command
mattermost-list-channels
Input
| Argument Name | Description | Required |
|---|---|---|
| team | The name of the team to list channels from. Default is the team name from the integration configuration. | Optional |
| include_private_channels | Whether to include private channels. Default is false. Possible values are: true, false. | Optional |
| page | The page number to retrieve. Default value is 0. | Optional |
| page_size | The size of the page to retrieve. Default value is 50. | Optional |
| limit | How many results to retrieve. Will override the page and page_size arguments if given. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.Channel.id | String | The ID of the channel. |
| Mattermost.Channel.create_at | Unknown | When was the channel created. |
| Mattermost.Channel.update_at | Unknown | When was the channel updated. |
| Mattermost.Channel.delete_at | Unknown | When was the channel deleted. |
| Mattermost.Channel.display_name | String | The display name of the channel. |
| Mattermost.Channel.name | String | The name of the channel. |
| Mattermost.Channel.description | String | The description of the channel. |
| Mattermost.Channel.header | String | The header of the channel. |
| Mattermost.Channel.purpose | String | The purpose of the channel. |
| Mattermost.Channel.last_post_at | Unknown | When was the last post to the channel made. |
| Mattermost.Channel.total_msg_count | Unknown | The total massage count of the channel. |
| Mattermost.Channel.extra_update_at | Unknown | When was the channel updated. |
| Mattermost.Channel.creator_id | String | The creator ID of the channel. |
Command example
!mattermost-list-channels limit=2 include_private_channels=true
Context Example
{
"Mattermost": {
"Channel": [
{
"create_at": 1697024204532,
"creator_id": "creator_id",
"delete_at": 0,
"display_name": "Name",
"extra_update_at": 0,
"group_constrained": null,
"header": "",
"id": "id",
"last_post_at": 1712503619042,
"last_root_post_at": 1712503619042,
"name": "name",
"policy_id": null,
"props": null,
"purpose": "",
"scheme_id": null,
"shared": null,
"team_id": "team_id",
"total_msg_count": 58,
"total_msg_count_root": 56,
"type": "O",
"update_at": 1697024204532
},
{
"create_at": 1696486762650,
"creator_id": "",
"delete_at": 0,
"display_name": "Off-Topic",
"extra_update_at": 0,
"group_constrained": null,
"header": "",
"id": "id",
"last_post_at": 1712501916866,
"last_root_post_at": 1712501916866,
"name": "off-topic",
"policy_id": null,
"props": null,
"purpose": "",
"scheme_id": null,
"shared": null,
"team_id": "team_id",
"total_msg_count": 4,
"total_msg_count_root": 4,
"type": "O",
"update_at": 1696486762650
}
]
}
}
Human Readable Output
Channels
name display_name type id name Display_Name O id off-topic Off-Topic O id
mattermost-list-private-channels-for-user
Get all the private channels on a team for a user.
Required Permissions
Logged in as the user, or have edit_other_users permission, and view_team permission for the team.
Base Command
mattermost-list-private-channels-for-user
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The name of the team to list channels from. Default is the team name from the integration configuration. | Optional |
| user_id | User ID to get channel memberships for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.User.Channels | Unknown | List of channels where the user is member of. |
| Mattermost.User.id | String | The ID of the user. |
Command example
!mattermost-list-private-channels-for-user user_id=user_id team_name=panw
Context Example
{
"Mattermost": {
"User": [
{
"channel_id": "channel_id",
"user_id": "user_id",
"roles": "Admin",
"last_viewed_at": 0,
"msg_count": 0,
"mention_count": 0,
"notify_props": {},
"last_update_at": 0
}
]
}
}
Human Readable Output
Channels for UserName
name display_name type id name Display_Name O channel_id
mattermost-create-channel
Creates a channel.
Required Permissions
If creating a public channel, create_public_channel permission is required. If creating a private channel, create_private_channel permission is required.
Base Command
mattermost-create-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| display_name | The display name of the channel to create. | Required |
| name | The name of the channel to create. | Required |
| type | The type of the channel to create. Possible values are: public, private. Default is public. | Optional |
| purpose | The purpose of the channel to create. | Optional |
| header | The header of the channel to create. | Optional |
| team | The team name of the channel to create. Default is the team name from the integration configuration. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.Channel.id | String | The ID of the channel. |
| Mattermost.Channel.create_at | Unknown | When was the channel created. |
| Mattermost.Channel.update_at | Unknown | When was the channel updated. |
| Mattermost.Channel.delete_at | Unknown | When was the channel deleted. |
| Mattermost.Channel.display_name | String | The display name of the channel. |
| Mattermost.Channel.name | String | The name of the channel. |
| Mattermost.Channel.description | String | The description of the channel. |
| Mattermost.Channel.header | String | The header of the channel. |
| Mattermost.Channel.purpose | String | The purpose of the channel. |
| Mattermost.Channel.last_post_at | Unknown | When was the last post to the channel made. |
| Mattermost.Channel.total_msg_count | Unknown | The total massage count of the channel. |
| Mattermost.Channel.extra_update_at | Unknown | When was the channel updated. |
| Mattermost.Channel.creator_id | String | The creator ID of the channel. |
| Mattermost.Channel.scheme_id | String | The scheme ID of the channel. |
Command example
!mattermost-create-channel display_name=channel_name name=channel_name type=Private
Context Example
{
"Mattermost": {
"Channel": {
"create_at": 1712649608411,
"creator_id": "creator_id",
"delete_at": 0,
"display_name": "channel_name",
"extra_update_at": 0,
"group_constrained": null,
"header": "",
"id": "id",
"last_post_at": 1712649608426,
"last_root_post_at": 1712649608426,
"name": "channel_name",
"policy_id": null,
"props": null,
"purpose": "",
"scheme_id": null,
"shared": null,
"team_id": "team_id",
"total_msg_count": 0,
"total_msg_count_root": 0,
"type": "P",
"update_at": 1712649608411
}
}
}
Human Readable Output
Channel channel_name was created successfully.
mattermost-add-channel-member
Adds a channel member.
Required Permissions
No permissions required.
Base Command
mattermost-add-channel-member
Input
| Argument Name | Description | Required |
|---|---|---|
| team | The team name of the channel to add the user to. Default is the team name from the integration configuration. | Optional |
| channel | The name of the channel to add the user to. | Required |
| user_id | The ID of the user to add. Use the command ‘mattermost-list-users’ to fetch the user ID. | Required |
Context Output
There is no context output for this command.
mattermost-remove-channel-member
Removes a channel member.
Required Permissions
manage_public_channel_members permission if the channel is public. manage_private_channel_members permission if the channel is private.
Base Command
mattermost-remove-channel-member
Input
| Argument Name | Description | Required |
|---|---|---|
| team | The team name of the channel to add the user to. Default is the team name from the integration configuration. | Optional |
| channel | The channel name of the channel to remove the user from. | Required |
| user_id | The ID of the user to remove. Use the command ‘mattermost-list-users’ to fetch the user ID. | Required |
Context Output
There is no context output for this command.
mattermost-list-users
Lists users.
Required Permissions
Requires an active session and (if specified) membership to the channel or team being selected from.
Base Command
mattermost-list-users
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The name of the team to filter users by. | Optional |
| channel | The name of the channel to filters users by. If mentioned, a team name must be mentioned as well. | Optional |
| page | The page number to retrieve. Should be provided with the page_size argument. Default value is 0. | Optional |
| page_size | The size of the page to retrieve. Should be provided with the page argument. Default value is 50. | Optional |
| limit | How many results to retrieve. If provided, overrides the page and page_size arguments. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.User.id | String | The ID of the user. |
| Mattermost.User.create_at | Unknown | When was the user created. |
| Mattermost.User.update_at | Unknown | When was the user updated. |
| Mattermost.User.delete_at | Unknown | When was the user deleted. |
| Mattermost.User.username | String | The username of the user. |
| Mattermost.User.auth_data | String | The authorization data of the user. |
| Mattermost.User.auth_service | String | The authorization service of the user. |
| Mattermost.User.email | String | The email of the user. |
| Mattermost.User.nickname | String | The nickname of the user. |
| Mattermost.User.first_name | Unknown | The first name of the user. |
| Mattermost.User.last_name | Unknown | The last name of the user. |
| Mattermost.User.position | Unknown | The position of the user. |
| Mattermost.User.roles | String | The roles of the channel. |
| Mattermost.User.locale | String | The locale of the channel. |
| Mattermost.User.timezone | Unknown | The timezone of the user. |
Command example
!mattermost-list-users limit=2 team_name=panw
Context Example
{
"Mattermost": {
"User": [
{
"auth_data": "",
"auth_service": "",
"create_at": 1696486752272,
"delete_at": 0,
"disable_welcome_email": false,
"email": "email",
"first_name": "",
"id": "id",
"last_name": "",
"locale": "en",
"nickname": "",
"position": "",
"roles": "system_admin system_user",
"timezone": {
"automaticTimezone": "Asia/Jerusalem",
"manualTimezone": "",
"useAutomaticTimezone": "true"
},
"update_at": 1696486762658,
"username": "admin"
},
{
"auth_data": "",
"auth_service": "",
"create_at": 1696500307646,
"delete_at": 0,
"disable_welcome_email": false,
"email": "email",
"first_name": "",
"id": "id",
"last_name": "",
"locale": "en",
"nickname": "",
"position": "",
"roles": "system_user system_admin",
"timezone": {
"automaticTimezone": "Asia/Jerusalem",
"manualTimezone": "",
"useAutomaticTimezone": "true"
},
"update_at": 1697354262697,
"username": "username"
}
]
}
}
Human Readable Output
Users
username role id admin admin@admin.com 8a6t7whumbdbxrawretujh6rre dev admin@ddev.com o9hpcwz73fdwxe9adue8jxo16o
mattermost-send-file
Sends a file.
Required Permissions
Must have upload_file permission.
Base Command
mattermost-send-file
Command example
!mattermost-send-file message=check entry_id=85@109 channel=test
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The team name of the channel to send the file to. Default is the team name from the integration configuration. | Optional |
| channel | The channel name of the channel to send the file to. Cannot be combined with the to argument. | Optional |
| message | The message to send to the channel along with the file. | Required |
| entry_id | The entry ID of the file. | Required |
| to | The username or email of the user to send the file to. | Optional |
Context Output
There is no context output for this command.
Human Readable Output
file test.txt was successfully sent to channel test
send-notification
Send a message using a chatbot app.
Required Permissions
Must have create_post permission for the channel the post is being created in.
Base Command
send-notification
Input
| Argument Name | Description | Required |
|---|---|---|
| message | The message to send. | Required |
| channel | The channel name to send the notification to. Default value is the channel configuration parameter. | Optional |
| entry | An entry ID to send as a link. | Optional |
| to | The username or email of the user to send the file to. | Optional |
| ignoreAddURL | Adds the War Room link to the message. Possible values are: true, false. | Optional |
| mattermost_ask | The message as a JSON for asking questions to the user. Default value is false. Possible values are: true, false. | Optional |
Context Output
There is no context output for this command.
mattermost-close-channel
Closes a channel.
Required Permissions
delete_public_channel permission if the channel is public. delete_private_channel permission if the channel is private, or has manage_system permission.
Base Command
mattermost-close-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The team name of the channel to close. Default value is the team name from the integration configuration. | Optional |
| channel | The channel name of the channel to close. If not provided, the mirrored investigation channel is archived (if the channel exists). | Optional |
Context Output
There is no context output for this command.
close-channel
Closes a mirrored MatterMost channel. If not provided, the mirrored investigation channel is archived (if the channel exists).
Required Permissions
delete_public_channel permission if the channel is public. delete_private_channel permission if the channel is private, or has manage_system permission.
Base Command
close-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The team name of the channel to delete. Default value is the team name from the integration configuration. | Optional |
| channel | The channel name of the channel to close. | Optional |
Context Output
There is no context output for this command.
mirror-investigation
Mirrors the investigation between Mattermost and the Cortex XSOAR War Room.
Required Permissions
No permissions required.
Base Command
mirror-investigation
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The mirroring type. Can be “all”, which mirrors everything, “chat”, which mirrors only chats (not commands), or “none”, which stops all mirroring. Possible values are: all, chat, none. Default is all. | Optional |
| autoclose | Whether the channel is auto-closed when an investigation is closed. Possible values are: true, false. Default is true. | Optional |
| direction | The mirroring direction. Possible values are: Both, FromDemisto, ToDemisto. Default is Both. | Optional |
| channel | The name of the channel. The default is “incident-<incidentID>”. | Optional |
| kickAdmin | Whether to remove the admin from the newly created channel. Default value is false. Possible values are: true, false. Default is false. | Optional |
| mirrorTo | Mirrors the investigation to a group (private channel) or a public channel. Default is group. Possible values are: group, channel. Default is group. | Optional |
Context Output
There is no context output for this command.
close-channel
Closes a mirrored Mattermost channel. If not provided, the mirrored investigation channel is archived (if the channel exists).
Base Command
close-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| team_name | The team name of the channel to delete. Default value is the team name from the integration configuration. | Optional |
| channel_name | The channel name of the channel to delete. | Optional |
Context Output
There is no context output for this command.
mattermost-mirror-investigation
Mirrors the investigation between Mattermost and the Cortex XSOAR War Room.
Required Permissions
No permissions channel.
Base Command
mattermost-mirror-investigation
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The mirroring type. Can be “all”, which mirrors everything, “chat”, which mirrors only chats (not commands), or “none”, which stops all mirroring. Possible values are: all, chat, none. Default is all. | Optional |
| autoclose | Whether the channel is auto-closed when an investigation is closed. Possible values are: true, false. Default is true. | Optional |
| direction | The mirroring direction. Possible values are: Both, FromDemisto, ToDemisto. Default is Both. | Optional |
| channel | The name of the channel. The default is “incident-<incidentID>”. | Optional |
| kickAdmin | Whether to remove the admin from the newly created channel. Default value is false. Possible values are: true, false. Default is false. | Optional |
| mirrorTo | Mirrors the investigation to a group (private channel) or a public channel. Possible values are: group, channel. Default is group. | Optional |
Context Output
There is no context output for this command.
mattermost-list-groups
Lists groups. Groups are available on Enterprise and Professional plans. Minimum server version: 5.11
Required Permissions
No permissions required.
Base Command
mattermost-list-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| page | The page number to retrieve. Default value is 0. | Optional |
| page_size | The size of the page to retrieve. Default value is 50. | Optional |
| limit | How many results to retrieve. Will override the page and page_size arguments if given. | Optional |
| group | Search for a specific user by this pattern. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.Groups.id | String | The ID of the group. |
| Mattermost.Groups.create_at | Unknown | The datetime the group was created. |
| Mattermost.Groups.update_at | Unknown | The datetime the group was updated. |
| Mattermost.Groups.delete_at | Unknown | The datetime the group was deleted. |
| Mattermost.Groups.display_name | String | The display name of the group. |
| Mattermost.Groups.name | String | The name of the group. |
| Mattermost.Groups.description | String | The description of the group. |
| Mattermost.Groups.source | String | The source of the group. |
| Mattermost.Groups.remote_id | String | The remote ID of the group. |
| Mattermost.Groups.has_syncables | boolean | If the group has any syncables. |
Command example
#### Context Example
```json
{
"Mattermost": {
"Groups": [
{
"id": "0815xyz",
"name": "name",
"display_name": "display name",
"description": "description",
"source": "custom",
"remote_id": null,
"create_at": 0,
"update_at": 0,
"delete_at": 0,
"has_syncables": false
},
{
"id": "0815abc",
"name": "name",
"display_name": "display name",
"description": "",
"source": "custom",
"remote_id": null,
"create_at": 0,
"update_at": 0,
"delete_at": 0,
"has_syncables": false
}
]
}
}
Human Readable Output
Groups
name display_name description id name display name 0815abc name display name description 0815xyz
mattermost-list-group-members
Lists group members. Groups are available on Enterprise and Professional plans. Minimum server version: 5.11
Required Permissions
Must have manage_system permission.
Base Command
mattermost-list-group-members
Input
| Argument Name | Description | Required |
|---|---|---|
| page | The page number to retrieve. Default value is 0. | Optional |
| page_size | The size of the page to retrieve. Default value is 50. | Optional |
| limit | How many results to retrieve. Will override the page and page_size arguments if given. | Optional |
| group_id | The group ID of the user group to list members for. Use the command ‘mattermost-list-groups’ to fetch the group ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Mattermost.Members.id | String | The ID of the group member. |
| Mattermost.Members.first_name | String | The first name of the group member. |
| Mattermost.Members.last_name | String | The last name of the group member. |
| Mattermost.Members.username | String | The username of the group member. |
Command example
!mattermost-list-group-members group_id=group_id
Human Readable Output
Group moi9ygz8qby1pr1xgkcfuqww9r members (2/2)
username id username1 admin@admin.com 8a6t7whumbdbxrawretujh6rre username2 admin@ddev.com o9hpcwz73fdwxe9adue8jxo16o
mattermost-add-group-member
Add group member(s). Groups are available on Enterprise and Professional plans. Minimum server version: 6.3
Required Permissions
Must have custom_group_manage_members permission for the given group.
Base Command
mattermost-add-group-member
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | The group ID of the user group to list members for. Use the command ‘mattermost-list-groups’ to fetch the group ID. | Required |
| user_ids | A comma-separated list of IDs of the users to add. Use the command ‘mattermost-list-users’ to fetch the user ID(s). | Required |
Context Output
There is no context output for this command.
Command example
!mattermost-add-group-member group_id=group_id user_ids=user_ids
Human Readable Output
The member username was added to the group successfully, with group ID: moi9ygz8qby1pr1xgkcfuqww9r
mattermost-remove-group-member
Remove group member(s). Groups are available on Enterprise and Professional plans. Minimum server version: 6.3
Required Permissions
Must have custom_group_manage_members permission for the given group.
Base Command
mattermost-remove-group-member
Input
| Argument Name | Description | Required |
|---|---|---|
| group_id | The group ID of the user group to list members for. Use the command ‘mattermost-list-groups’ to fetch the group ID. | Required |
| user_ids | A comma-separated list of IDs of the users to remove. Use the command ‘mattermost-list-users’ to fetch the user ID(s). | Required |
Context Output
There is no context output for this command.
Command example
!mattermost-remove-group-member group_id=group_id user_ids=user_ids
Human Readable Output
The member username was removed from group successfully, with group ID: moi9ygz8qby1pr1xgkcfuqww9r
mattermost-set-channel-role
Update a user’s roles for a channel. The user has to already be a member of the channel.
Required Permissions
Must have manage_channel_roles permission for the channel.
Base Command
mattermost-set-channel-role
Input
| Argument Name | Description | Required |
|---|---|---|
| channel_id | The channel ID to set the role in. Use the command ‘mattermost-list-channels’ to fetch the channel ID. | Required |
| user_id | The ID of the user to set role for. Use the command ‘mattermost-list-users’ to fetch the user ID. | Required |
| role | The role to set for the user. Possible values are: Admin, Member. Default is Member. | Optional |
Context Output
There is no context output for this command.
Breaking changes from the previous version of this integration - Mattermost v2
A new required configuration parameters was added: Bot Access Token.
Configuration parameters
url— Server URL (required)bot_access_token— (required)personal_access_token— (required)team_name— Team Name (required)notification_channel— Default Notifications Channelmirroring— Enable Incident Mirroringallow_incidents— Allow external users to create incidents via DM.permitted_notifications— Types of Notifications to SendlongRunning— Long running instance. Required for investigation mirroring and direct messages.insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (18)
-
close-channelCloses a mirrored Mattermost channel. If not provided, the mirrored investigation channel is archived (if the channel exists).
-
mattermost-add-channel-memberAdds a channel member.
-
mattermost-add-group-memberAdd group member(s). Groups are available on Enterprise and Professional plans. Minimum server version: 6.3
-
mattermost-close-channelCloses a channel.
-
mattermost-create-channelCreates a channel.
-
mattermost-get-teamGets a team's details.
-
mattermost-list-channelsLists channels.
-
mattermost-list-group-membersLists group members. Groups are available on Enterprise and Professional plans. Minimum server version: 5.11
-
mattermost-list-groupsLists groups. Groups are available on Enterprise and Professional plans. Minimum server version: 5.11
-
mattermost-list-private-channels-for-userGet all the private channels on a team for a user.
-
mattermost-list-usersLists users.
-
mattermost-mirror-investigationMirrors the investigation between Mattermost and the Cortex XSOAR War Room.
-
mattermost-remove-channel-memberRemoves a channel member.
-
mattermost-remove-group-memberRemove group member(s). Groups are available on Enterprise and Professional plans. Minimum server version: 6.3
-
mattermost-send-fileSends a file.
-
mattermost-set-channel-roleUpdate a user's roles for a channel. The user has to already be a member of the channel.
-
mirror-investigationMirrors the investigation between Mattermost and the Cortex XSOAR War Room.
-
send-notificationSend a message using a chatbot app.
import json from unittest.mock import patch import demistomock as demisto import pytest from freezegun import freeze_time from MattermostV2 import ( INCIDENT_NOTIFICATION_CHANNEL, add_channel_member_command, add_group_member_command, answer_question, close_channel_command, create_channel_command, create_incidents, event_handler, extract_entitlement, get_channel_id_from_context, get_channel_id_to_send_notif, get_team_command, get_war_room_url, handle_posts, handle_text_received_from_mm, list_channels_command, list_groups_command, list_group_members_command, list_private_channels_for_user_command, list_users_command, mirror_investigation, remove_channel_member_command, remove_group_member_command, send_file_command, send_notification, set_channel_role_command, ) def util_load_json(path): with open(path, encoding="utf-8") as f: return json.loads(f.read()) def http_mock( method: str, url_suffix: str = "", full_url: str = "", params: dict = {}, data: dict = {}, files: dict = {}, json_data: dict = {}, headers: dict = {}, ): if "bot_access_token" in headers.get("Authorization", ""): if url_suffix == "/api/v4/users/me": return util_load_json("test_data/get_bot_response.json") if url_suffix == "/api/v4/posts": return util_load_json("test_data/create_post_response.json") if url_suffix == "/api/v4/teams/name/team_name": return util_load_json("test_data/get_team_response.json") elif url_suffix == "/api/v4/teams/team_id/channels" or url_suffix == "/api/v4/teams/team_id/channels/private": return util_load_json("test_data/list_channels_response.json") elif url_suffix == "/api/v4/users/user_id/teams/team_id/channels": return util_load_json("test_data/list_channel_memberships_for_user.json") elif url_suffix == "/api/v4/channels": return util_load_json("test_data/create_channel_response.json") elif url_suffix == "/api/v4/users": return util_load_json("test_data/list_users_response.json") elif url_suffix == "/api/v4/files": return util_load_json("test_data/send_file_response.json") elif ( url_suffix == "/api/v4/users/email/user_email" or url_suffix == "/api/v4/users/username/username" or url_suffix == "/api/v4/users/me" or url_suffix == "/api/v4/users/user_id" ): return util_load_json("test_data/list_users_response.json")[0] elif url_suffix == "/api/v4/users/username/username2": return util_load_json("test_data/list_users_response.json")[1] elif url_suffix == "/api/v4/channels/direct": channel = util_load_json("test_data/create_channel_response.json") channel["id"] = "direct_id" channel["type"] = "D" return channel elif url_suffix == "/api/v4/channels/group": channel = util_load_json("test_data/create_channel_response.json") channel["id"] = "group_id" channel["type"] = "G" return channel elif url_suffix == "/api/v4/groups": return util_load_json("test_data/list_groups_response.json") elif url_suffix == "/api/v4/groups/group_id/members": return util_load_json("test_data/list_group_members_response.json") else: return {} @pytest.fixture(autouse=True) def ws_client(mocker): from MattermostV2 import WebSocketClient return WebSocketClient( base_url="mock url", verify=True, proxy=False, token="personal_access_token", ) @pytest.fixture(autouse=True) def http_client(mocker): from MattermostV2 import HTTPClient headers = {"Authorization": "Token mock"} http_client = HTTPClient( base_url="mock url", headers=headers, verify=True, proxy=False, bot_access_token="bot_access_token", personal_access_token="personal_access_token", team_name="team_name", notification_channel="notification_channel", ) mocker.patch.object(http_client, "_http_request", side_effect=http_mock) return http_client def test_get_team_command(http_client): """ Given: A mock MatterMost client. When: Running get_team_command with a team name. Then: Ensure we get the result. """ args = {"team_name": "team_name"} results = get_team_command(http_client, args) assert results.outputs.get("name", "") == "team_name" def test_list_channels_command(http_client): """ Given: A mock MatterMost client. When: Running list_channels_command with a team name. Then: Ensure we get the result. """ args = {"team_name": "team_name", "include_private_channels": True} results = list_channels_command(http_client, args) assert results.outputs[0].get("name") == "name" assert len(results.outputs) == 2 def test_list_private_channels_for_user_command(http_client): """ Given: A mock MatterMost client. When: Running list_private_channels_for_user_command with a team name and user id. Then: Ensure we get the result. """ args = {"team_name": "team_name", "user_id": "user_id"} results = list_private_channels_for_user_command(http_client, args) assert results.outputs["channels"][0].get("name") == "name" assert len(results.outputs["channels"]) == 1 def test_create_channel_command(http_client): """ Given: A mock MatterMost client. When: Running create_channel_command with a team name. Then: Ensure we get the result. """ args = { "team_name": "team_name", "name": "channel_name", "display_name": "display_name", "type": "Public", "purpose": "purpose", "header": "header", } results = create_channel_command(http_client, args) assert results.outputs.get("name") == "name" def test_add_channel_member_command(http_client): """ Given: A mock MatterMost client. When: Running add_channel_member_command with a team name. Then: Ensure we get the result. """ args = { "team_name": "team_name", "channel_name": "channel_name", "user_id": "user_id", } results = add_channel_member_command(http_client, args) assert "The member username was added to the channel successfully" in results.readable_output def test_remove_channel_member_command(http_client): """ Given: A mock MatterMost client. When: Running remove_channel_member_command with a team name. Then: Ensure we get the result. """ args = { "team_name": "team_name", "channel_name": "channel_name", "user_id": "user_id", } results = remove_channel_member_command(http_client, args) assert "The member username was removed from the channel successfully." in results.readable_output def test_list_users_command(http_client): """ Given: A mock MatterMost client. When: Running list_users_command with a team name. Then: Ensure we get the result. """ args = { "team_name": "team_name", "channel_id": "channel_id", } results = list_users_command(http_client, args) assert results.outputs[0].get("first_name") == "first_name" def test_close_channel_command_no_mirror(http_client): """ Given: A mock MatterMost client. When: Running close_channel_command with a team name. Then: Ensure we get the result. """ args = { "team_name": "team_name", "channel": "channel_name", } results = close_channel_command(http_client, args) assert "The channel channel_name was delete successfully." in results.readable_output def test_close_channel_command_mirror(http_client, mocker): """ Given: A mock MatterMost client. When: Running close_channel_command with a team name. Then: Ensure we get the result, and was called only once with the first mirror """ args = { "team_name": "team_name", "channel": "channel_name", } import MattermostV2 MattermostV2.CACHE_EXPIRY = False MattermostV2.CACHED_INTEGRATION_CONTEXT = "" mock_integration_context = { "mirrors": json.dumps( [ { "channel_name": "Channel1", "team_id": "team_id", "channel_id": "channel_id", "mirrored": False, "investigation_id": "Incident123", "mirror_direction": "toDemisto", "auto_close": True, "mirror_type": "all", }, { "channel_name": "Channel2", "team_id": "team_id", "channel_id": "channel_id_different_channel", "mirrored": True, "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, "mirror_type": "chat", }, ] ) } mocker.patch("MattermostV2.get_integration_context", return_value=mock_integration_context) mocker.patch.object(demisto, "investigation", return_value={"id": "Incident123"}) mocker.patch.object(demisto, "mirrorInvestigation") results = close_channel_command(http_client, args) demisto.mirrorInvestigation.assert_called_once_with("Incident123", "none:toDemisto", True) assert "The channel channel_name was delete successfully." in results.readable_output def test_send_file_command(http_client, mocker): """ Given: A mock MatterMost client. When: Running send_file_command with a team name. Then: Ensure we get the result. """ expected_file_info = {"name": "test_file.txt", "path": "/path/to/test_file.txt"} mocker.patch("MattermostV2.demisto.getFilePath", return_value=expected_file_info) mocker.patch.object(http_client, "send_file_request", return_value=util_load_json("test_data/send_file_response.json")) args = { "team_name": "team_name", "channel": "channel_name", } send_file_command(http_client, args) def test_get_channel_id_to_send_notif(http_client, mocker): """ Given: A mock MatterMost client. When: Running get_channel_id_to_send_notif for a single user. Then: Ensure we get the result. """ results = get_channel_id_to_send_notif(http_client, ["username"], "channel_name", "investigation_id") assert results == "direct_id" def test_get_channel_id_to_send_notif_multiple_users(http_client, mocker): """ Given: A mock MatterMost client. When: Running get_channel_id_to_send_notif for two users. Then: Ensure we get the result. """ results = get_channel_id_to_send_notif(http_client, ["username", "username2"], "channel_name", "investigation_id") assert results == "group_id" def test_get_channel_id_from_context(mocker): """ Given: A mock MatterMost client. When: Running get_channel_id_from_context. Then: Ensure we get the result. """ import MattermostV2 MattermostV2.CACHE_EXPIRY = False MattermostV2.CACHED_INTEGRATION_CONTEXT = "" mock_integration_context = { "mirrors": json.dumps( [ { "channel_name": "Channel1", "team_id": "team_id", "channel_id": "ID1", "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, }, { "channel_name": "Channel2", "team_id": "team_id", "channel_id": "ID2", "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, }, ] ) } mocker.patch("MattermostV2.get_integration_context", return_value=mock_integration_context) results = get_channel_id_from_context("Channel1", "Incident123") assert results def test_save_entitlement(): """ Given: - arguments. When: - Calling the save_entitlement function. Then: - Validate that the mocked functions were called with the expected arguments """ entitlement = "Test Entitlement" message_id = "123" reply = "Test Reply" expiry = "2023-09-09" default_response = "Default Response" to_id = "user@example.com" OBJECTS_TO_KEYS = { "mirrors": "investigation_id", "messages": "entitlement", } with ( patch("MattermostV2.get_integration_context") as mock_get_integration_context, patch("MattermostV2.set_to_integration_context_with_retries") as mock_set_integration_context, ): mock_get_integration_context.return_value = {"messages": []} fixed_timestamp = "2023-09-09T20:08:50Z" with freeze_time(fixed_timestamp): from MattermostV2 import save_entitlement save_entitlement(entitlement, message_id, reply, expiry, default_response, to_id) expected_data = { "messages": [ { "root_id": message_id, "entitlement": entitlement, "reply": reply, "expiry": expiry, "sent": fixed_timestamp, "default_response": default_response, "to_id": to_id, } ] } mock_get_integration_context.assert_called_once_with() mock_set_integration_context.assert_called_once_with(expected_data, OBJECTS_TO_KEYS) @pytest.mark.parametrize( "entitlement, expected_result", [ ("guid123@incident456|task789", ("guid123", "incident456", "task789")), # Scenario 1: Full entitlement ("guid123@incident456", ("guid123", "incident456", "")), # Scenario 2: No task ID ("guid123@", ("guid123", "", "")), # Scenario 3: No incident ID or task ID ], ) def test_extract_entitlement(entitlement, expected_result): """ Test the extract_entitlement function. Given: - Input entitlement string. When: - Calling the extract_entitlement function with the given input entitlement. Then: - Validate that the function correctly extracts the entitlement components: guid, incident_id, and task_id. """ result = extract_entitlement(entitlement) assert result == expected_result def test_mirror_investigation_create_new_channel(http_client, mocker): """ Given a mock client and relevant arguments, When calling the mirror_investigation function to create a new channel, Then validate that the function returns the expected CommandResults. """ import MattermostV2 MattermostV2.MIRRORING_ENABLED = True MattermostV2.LONG_RUNNING = True MattermostV2.SYNC_CONTEXT = True mocker.patch.object(demisto, "demistoUrls", return_value={"server": "mock_server_url"}) # Test data args = { "type": "all", "direction": "Both", "channelName": "mirror-channel", "autoclose": True, } mock_integration_context = { "mirrors": json.dumps( [ { "channel_name": "Channel1", "team_id": "team_id", "channel_id": "channel_id", "mirrored": False, "investigation_id": "Incident123", "mirror_direction": "toDemisto", "auto_close": True, "mirror_type": "all", }, { "channel_name": "Channel2", "team_id": "team_id", "channel_id": "channel_id", "mirrored": True, "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, "mirror_type": "chat", }, ] ) } mocker.patch("MattermostV2.get_integration_context", return_value=mock_integration_context) mocker.patch.object(demisto, "mirrorInvestigation") # Call the function result = mirror_investigation(http_client, **args) # Assert the result demisto.mirrorInvestigation.assert_called_once_with("1", "all:Both", True) assert "Investigation mirrored successfully" in result.readable_output def test_send_notification_command_with_not_permitted_notif_type(http_client, mocker): """ Given - client When - send message to channel Then - Validate that """ import MattermostV2 MattermostV2.PERMITTED_NOTIFICATION_TYPES = [] mocker.patch.object(http_client, "send_notification_request", return_value={"id": "message_id"}) result = send_notification(http_client, user_id="user1", message="Hello", to="channel1", messageType="not permitted") assert result == "Message type is not in permitted options. Received: not permitted" def test_send_notification_command_with_generic_notif_channel_name(http_client, mocker): """ Given - client When - send message to channel Then - Validate that """ import MattermostV2 MattermostV2.PERMITTED_NOTIFICATION_TYPES = ["incidentOpened"] mocker.patch.object(http_client, "send_notification_request", return_value={"id": "message_id"}) mocker.patch.object(MattermostV2, "get_channel_id_from_context", return_value="channel_id") result = send_notification( http_client, user_id="user1", message="Hello", channel=INCIDENT_NOTIFICATION_CHANNEL, messageType="incidentOpened" ) assert result.readable_output == "Message sent to MatterMost successfully. Message ID is: message_id" def test_send_notification_command(http_client, mocker): """ Given - client When - send message to channel Then - Validate that """ mocker.patch.object(http_client, "send_notification_request", return_value={"id": "message_id"}) result = send_notification( http_client, user_id="user1", message="Hello", to="channel1", ) assert result.readable_output == "Message sent to MatterMost successfully. Message ID is: message_id" def test_list_groups_command(http_client): """ Given - client arguments When - list group Then - Validate that the function returns the expected CommandResults. """ args = { "group": "user_group", } results = list_groups_command(http_client, args) assert results.outputs[0].get("id") == "group_id" def test_list_group_members_command(http_client): """ Given - client arguments When - list group members Then - Validate that the function returns the expected CommandResults. """ args = { "group_id": "group_id", } results = list_group_members_command(http_client, args) assert len(results.outputs) == 1 assert results.outputs[0]["username"] == "username" def test_add_group_member_command(http_client): """ Given - client arguments When - add group member Then - Validate that the function returns the expected CommandResults. """ args = {"group_id": "group_id", "user_ids": "user_id"} results = add_group_member_command(http_client, args) assert results.readable_output == "The member username was added to the group successfully, with group ID: group_id" def test_remove_group_member_command(http_client): """ Given - client arguments When - remove group member Then - Validate that the function returns the expected CommandResults. """ args = {"group_id": "group_id", "user_ids": "user_id"} results = remove_group_member_command(http_client, args) assert results.readable_output == "The member username was removed from the group successfully, with group ID: group_id" def test_set_channel_role_command(http_client, mocker): """ Given - client arguments When - remove user group member Then - Validate that the function returns the expected CommandResults. """ args = {"channel_id": "channel_id", "user_id": "user_id", "role": "admin"} mocker.patch.object(http_client, "remove_group_member_request", return_value={"status": "ok"}) results = set_channel_role_command(http_client, args) assert results.readable_output == "Set channel role for username successfully to Admin." ######### async tests ######### @pytest.mark.asyncio async def test_handle_posts_regular_post(http_client, mocker): """ Given: - Post payload. When: - Calling the handle_posts function. Then: - Validate that the mirror investigation func was called. only once, as one of the mirrors was already mirrored. """ import MattermostV2 payload = util_load_json("test_data/posted_data_user.json") mock_integration_context = { "mirrors": json.dumps( [ { "channel_name": "Channel1", "team_id": "team_id", "channel_id": "channel_id", "mirrored": False, "investigation_id": "Incident123", "mirror_direction": "toDemisto", "auto_close": True, "mirror_type": "all", }, { "channel_name": "Channel2", "team_id": "team_id", "channel_id": "channel_id", "mirrored": True, "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, "mirror_type": "chat", }, ] ) } MattermostV2.CLIENT = http_client MattermostV2.CACHE_EXPIRY = False mocker.patch("MattermostV2.get_integration_context", return_value=mock_integration_context) mocker.patch("MattermostV2.handle_text_received_from_mm", return_value=None) mocker.patch.object(demisto, "mirrorInvestigation") await handle_posts(payload) demisto.mirrorInvestigation.assert_called_once_with("Incident123", "all:toDemisto", True) @pytest.mark.asyncio async def test_handle_text(mocker): """ Given: - arguments. When: - Calling the handle_text_received_from_mm function. Then: - Validate that the `demisto.addEntry` method was called with the expected arguments """ investigation_id = "123" text = "Hello, this is a test message" operator_email = "test@example.com" operator_name = "Test User" MESSAGE_FOOTER = "\n**From Mattermost**" with patch("MattermostV2.demisto") as mock_demisto: await handle_text_received_from_mm(investigation_id, text, operator_email, operator_name) mock_demisto.addEntry.assert_called_once_with( id=investigation_id, entry=text, username=operator_name, email=operator_email, footer=MESSAGE_FOOTER ) @pytest.mark.asyncio async def test_event_handler_error(ws_client, mocker): """ Given: - Error post payload. When: - Calling the handle_posts function. Then: - Validate that the demisto.error func was called. """ error_payload = """{"status": "FAIL", "seq_reply": 2, "error": {"id": "some.error.id.here", "message": "Some error message here" } }""" error_mock = mocker.patch.object(demisto, "error") mocker.patch.object(demisto, "updateModuleHealth") await event_handler(ws_client, error_payload) assert error_mock.call_count == 1 @pytest.mark.asyncio async def test_event_handler_bot_message(http_client, mocker): """ Given: - Bot post payload. When: - Calling the handle_posts function. Then: - Validate that the demisto.debug func was called. """ import MattermostV2 MattermostV2.CLIENT = http_client bot_payload = util_load_json("test_data/posted_data_bot.json") mocker.patch.object(demisto, "updateModuleHealth") mocker.patch.object(demisto, "debug") await handle_posts(bot_payload) demisto.debug.assert_called_once_with("MM: Got a bot message. Will not mirror.") @pytest.mark.asyncio async def test_event_handler_direct_message(http_client, mocker): """ Given: - dm post payload. When: - Calling the handle_posts function. Then: - Validate that the demisto.debug func was called. """ import MattermostV2 MattermostV2.CLIENT = http_client MattermostV2.ALLOW_INCIDENTS = True payload = util_load_json("test_data/posted_data_user.json") payload["data"]["channel_type"] = "D" mocker.patch.object(demisto, "updateModuleHealth") mocker.patch.object(demisto, "directMessage", return_value={}) await handle_posts(payload) demisto.directMessage.assert_called_once_with("message", "", "", True) def test_answer_question(http_client, mocker): """ Test the answer_question function. Given: - A mocked question dictionary. When: - Calling the answer_question function with the mocked question. Then: - Validate that the function correctly handles the entitlement and returns the incident_id. """ import MattermostV2 MattermostV2.CLIENT = http_client mock_question = {"entitlement": "guid123@incident456|task789", "to_id": "123"} mocker.patch("MattermostV2.process_entitlement_reply") result = answer_question("Answer123", mock_question, "user@example.com") assert result == "incident456" @pytest.mark.asyncio async def test_create_incidents(mocker): """ Given: - Incidents When: - Calling the create_incidents function. Then: - Validate that the demisto.createIncidents func was called. """ mocker.patch.object(demisto, "createIncidents", return_value="nice") incidents = [{"name": "xyz", "details": "1.1.1.1,8.8.8.8"}] incidents_with_labels = [ { "name": "xyz", "details": "1.1.1.1,8.8.8.8", "labels": [ {"type": "Reporter", "value": "spengler"}, {"type": "ReporterEmail", "value": "test@test.com"}, {"type": "Source", "value": "Slack"}, ], } ] data = await create_incidents(incidents, "spengler", "test@test.com", "demisto_user") incident_arg = demisto.createIncidents.call_args[0][0] user_arg = demisto.createIncidents.call_args[1]["userID"] assert incident_arg == incidents_with_labels assert user_arg == "demisto_user" assert data == "nice" class TestGetWarRoomURL: def test_get_war_room_url_with_xsiam_from_incident_war_room(self, mocker): url = "https://example.com/WarRoom/INCIDENT-2930" expected_war_room_url = "https://example.com/incidents/war_room?caseId=2930" mocker.patch("MattermostV2.is_xsiam", return_value=True) mocker.patch.dict(demisto.callingContext, {"context": {"Inv": {"id": "INCIDENT-2930"}}}) assert get_war_room_url(url) == expected_war_room_url def test_get_war_room_url_without_xsiam_from_incident_war_room(self, mocker): url = "https://example.com/WarRoom/INCIDENT-2930" mocker.patch("MattermostV2.is_xsiam", return_value=False) expected_war_room_url = "https://example.com/WarRoom/INCIDENT-2930" assert get_war_room_url(url) == expected_war_room_url def test_get_war_room_url_with_xsiam_from_alert_war_room(self, mocker): url = "https://example.com/WarRoom/ALERT-1234" mocker.patch("MattermostV2.is_xsiam", return_value=True) mocker.patch.dict(demisto.callingContext, {"context": {"Inv": {"id": "1234"}}}) expected_war_room_url = ( "https://example.com/incidents/alerts_and_insights?caseId=1234&action:openAlertDetails=1234-warRoom" ) assert get_war_room_url(url) == expected_war_room_url