new: [action_mod] Added MatterMost module and deleted test modules

pull/572/head
Sami Mokaddem 2022-08-05 15:39:12 +02:00
parent cac0c19eed
commit 89bc8bf19c
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
6 changed files with 192 additions and 171 deletions

View File

@ -1 +1 @@
__all__ = ['testaction', 'blockaction', 'writeaction']
__all__ = ['testaction', 'mattermost']

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python
from jinja2.sandbox import SandboxedEnvironment
default_template = """
# Tutorial: How to use jinja2 templating
:warning: For these examples, we consider the module received data under the MISP core format
1. You can use the dot `.` notation or the subscript syntax `[]` to access attributes of a variable
- `{% raw %}{{ Event.info }}{% endraw %}` -> {{ Event.info }}
- `{% raw %}{{ Event['info'] }}{% endraw %}` -> {{ Event['info'] }}
2. Jinja2 allows you to easily create list:
```{% raw %}
{% for attribute in Event.Attribute %}
- {{ attribute.value }}
{% endfor %}
{% endraw %}```
Gives:
{% for attribute in Event.Attribute %}
- {{ attribute.value }}
{% endfor %}
3. Jinja2 allows you to add logic
```{% raw %}
{% if "tlp:white" in Event.Tag %}
- This Event has the TLP:WHITE tag
{% else %}
- This Event doesn't have the TLP:WHITE tag
{% endif %}
{% endraw %}```
Gives:
{% if "tlp:white" in Event.Tag %}
- This Event has the TLP:WHITE tag
{% else %}
- This Event doesn't have the TLP:WHITE tag
{% endif %}
## Jinja2 allows you to modify variables by using filters
3. The `reverse` filter
- `{% raw %}{{ Event.info | reverse }}{% endraw %}` -> {{ Event.info | reverse }}
4. The `format` filter
- `{% raw %}{{ "%s :: %s" | format(Event.Attribute[0].type, Event.Attribute[0].value) }}{% endraw %}` -> {{ "%s :: %s" | format(Event.Attribute[0].type, Event.Attribute[0].value) }}
5.The `groupby` filter
```{% raw %}
{% for type, attributes in Event.Attribute|groupby("type") %}
- {{ type }}{% for attribute in attributes %}
- {{ attribute.value }}
{% endfor %}
{% endfor %}
{% endraw %}```
Gives:
{% for type, attributes in Event.Attribute|groupby("type") %}
- {{ type }}{% for attribute in attributes %}
- {{ attribute.value }}
{% endfor %}
{% endfor %}
"""
def renderTemplate(data, template=default_template):
env = SandboxedEnvironment()
return env.from_string(template).render(data)

View File

@ -1,63 +0,0 @@
import json
import base64
misperrors = {'error': 'Error'}
# config fields that your code expects from the site admin
moduleconfig = {
};
# blocking modules break the exection of the chain of actions (such as publishing)
blocking = True
# returns either "boolean" or "data"
# Boolean is used to simply signal that the execution has finished.
# For blocking modules the actual boolean value determines whether we break execution
returns = 'boolean'
# the list of hook-points that it can hook
hooks = ['publish']
moduleinfo = {'version': '0.1', 'author': 'Andras Iklody',
'description': 'This module is merely a test, always returning true. Triggers on event publishing.',
'module-type': ['action']}
def handler(q=False):
if q is False:
return False
r = {"data": False, "error": "Barf."}
return r
def introspection():
modulesetup = {}
try:
responseType
modulesetup['responseType'] = responseType
except NameError:
pass
try:
inputSource
modulesetup['resultType'] = resultType
except NameError:
pass
try:
hooks
modulesetup['hooks'] = hooks
except NameError:
pass
try:
hooks
modulesetup['blocking'] = blocking
except NameError:
pass
return modulesetup
def version():
moduleinfo['config'] = moduleconfig
return moduleinfo

View File

@ -0,0 +1,97 @@
import json
from mattermostdriver import Driver
from ._utils import utils
misperrors = {'error': 'Error'}
# config fields that your code expects from the site admin
moduleconfig = {
'params': {
'mattermost_hostname': {
'type': 'string',
'description': 'The Mattermost domain',
'value': 'example.mattermost.com',
},
'bot_access_token': {
'type': 'string',
'description': 'Access token generated when you created the bot account',
},
'channel_id': {
'type': 'string',
'description': 'The channel you added the bot to',
},
'message_template': {
'type': 'large_string',
'description': 'The template to be used to generate the message to be posted',
'value': 'The **template** will be rendered using *Jinja2*!',
},
},
# Blocking modules break the exection of the current of action
'blocking': False,
# Indicates whether parts of the data passed to this module should be filtered. Filtered data can be found under the `filteredItems` key
'support_filters': True,
# Indicates whether the data passed to this module should be compliant with the MISP core format
'expect_misp_core_format': False,
}
# returns either "boolean" or "data"
# Boolean is used to simply signal that the execution has finished.
# For blocking modules the actual boolean value determines whether we break execution
returns = 'boolean'
moduleinfo = {'version': '0.1', 'author': 'Sami Mokaddem',
'description': 'Simplistic module to send message to a Mattermost channel.',
'module-type': ['action']}
def createPost(request):
params = request['params']
mm = Driver({
'url': params['mattermost_hostname'],
'token': params['bot_access_token'],
'scheme': 'https',
'basepath': '/api/v4',
'port': 443,
})
mm.login()
data = {}
if 'matchingData' in request:
data = request['matchingData']
else:
data = request['data']
if params['message_template']:
message = utils.renderTemplate(data, params['message_template'])
else:
message = '```\n{}\n```'.format(json.dumps(data))
mm.posts.create_post(options={
'channel_id': params['channel_id'],
'message': message
})
return True
def handler(q=False):
if q is False:
return False
request = json.loads(q)
createPost(request)
r = {"data": True}
return r
def introspection():
modulesetup = {}
try:
modulesetup['config'] = moduleconfig
except NameError:
pass
return modulesetup
def version():
moduleinfo['config'] = moduleconfig
return moduleinfo

View File

@ -1,34 +1,36 @@
import json
import base64
from ._utils import utils
misperrors = {'error': 'Error'}
# config fields that your code expects from the site admin
moduleconfig = {
'foo': {
'type': 'string',
'description': 'blablabla',
'value': 'xyz'
'params': {
'foo': {
'type': 'string',
'description': 'blablabla',
'value': 'xyz'
},
'Data extraction path': {
# Extracted data can be found under the `matchingData` key
'type': 'hash_path',
'description': 'Only post content extracted from this path',
'value': 'Attribute.{n}.AttributeTag.{n}.Tag.name',
},
},
'bar': {
'type': 'string',
'value': 'meh'
}
};
# blocking modules break the exection of the chain of actions (such as publishing)
blocking = False
# Blocking modules break the exection of the current of action
'blocking': False,
# Indicates whether parts of the data passed to this module should be extracted. Extracted data can be found under the `filteredItems` key
'support_filters': False,
# Indicates whether the data passed to this module should be compliant with the MISP core format
'expect_misp_core_format': False,
}
# returns either "boolean" or "data"
# Boolean is used to simply signal that the execution has finished.
# For blocking modules the actual boolean value determines whether we break execution
returns = 'boolean'
# the list of hook-points that it can hook
hooks = ['publish']
moduleinfo = {'version': '0.1', 'author': 'Andras Iklody',
'description': 'This module is merely a test, always returning true. Triggers on event publishing.',
'module-type': ['action']}
@ -37,33 +39,16 @@ moduleinfo = {'version': '0.1', 'author': 'Andras Iklody',
def handler(q=False):
if q is False:
return False
r = True
result = json.loads(q) # noqa
output = '' # Insert your magic here!
r = {"data": r}
request = json.loads(q) # noqa
success = True
r = {"data": success}
return r
def introspection():
modulesetup = {}
try:
responseType
modulesetup['responseType'] = responseType
except NameError:
pass
try:
inputSource
modulesetup['resultType'] = resultType
except NameError:
pass
try:
hooks
modulesetup['hooks'] = hooks
except NameError:
pass
try:
hooks
modulesetup['blocking'] = blocking
modulesetup['config'] = moduleconfig
except NameError:
pass
return modulesetup

View File

@ -1,68 +0,0 @@
import json
import base64
misperrors = {'error': 'Error'}
# config fields that your code expects from the site admin
moduleconfig = {
};
# blocking modules break the exection of the chain of actions (such as publishing)
blocking = False
# returns either "boolean" or "data"
# Boolean is used to simply signal that the execution has finished.
# For blocking modules the actual boolean value determines whether we break execution
returns = 'boolean'
# the list of hook-points that it can hook
hooks = ['publish']
moduleinfo = {'version': '0.1', 'author': 'Andras Iklody',
'description': 'This module is merely a test, writing a tmp file with the event info.',
'module-type': ['action']}
def handler(q=False):
if q is False:
return False
request = json.loads(q)
data = request["data"]
f = open("/var/www/MISP7/app/tmp/output.txt","w+")
f.write(data["Event"]["info"])
f.close()
r = {"data": True}
return r
def introspection():
modulesetup = {}
try:
responseType
modulesetup['responseType'] = responseType
except NameError:
pass
try:
inputSource
modulesetup['resultType'] = resultType
except NameError:
pass
try:
hooks
modulesetup['hooks'] = hooks
except NameError:
pass
try:
hooks
modulesetup['blocking'] = blocking
except NameError:
pass
return modulesetup
def version():
moduleinfo['config'] = moduleconfig
return moduleinfo