Merge branch 'ent-6958-messaging-integration' into 'develop'
messaging integrations See merge request artica/pandorafms!3793
This commit is contained in:
commit
f67528f7a5
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"python.pythonPath": "slack/venv/bin/python"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
venv
|
|
@ -0,0 +1,173 @@
|
|||
import requests, argparse, sys, os
|
||||
from datetime import datetime
|
||||
from re import search
|
||||
from base64 import b64decode
|
||||
from discord_webhook import DiscordWebhook, DiscordEmbed
|
||||
|
||||
|
||||
### Variables and arg parser ###
|
||||
parser = argparse.ArgumentParser(description='Test parser dic')
|
||||
parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True)
|
||||
parser.add_argument('-u', '--url', help='Discord webhook URL', required=True)
|
||||
parser.add_argument('-t', '--alert_tittle', help='Alert tittle', default='PandoraFMS alert fired')
|
||||
parser.add_argument('-D', '--alert_desc', help='Alert description', default='alert')
|
||||
parser.add_argument('-m', '--message', help='Discord message', default='')
|
||||
parser.add_argument('-T','--tittle_color', help='Alert tittle descripcion in HEX EX: 53e514', default="53e514")
|
||||
parser.add_argument('-A','--author', help='Alert custom author', default='PandoraFMS')
|
||||
parser.add_argument('-F','--footer', help='Custom footer', default='')
|
||||
parser.add_argument('--avatar_url', help='Custom avatar URL for the user which send the alert', default='')
|
||||
parser.add_argument('--author_url', help='Alert custom url author', default='')
|
||||
parser.add_argument('--author_icon_url', help='Alert custom author icon url ', default='')
|
||||
parser.add_argument('--thumb', help='Custom thumbnail url', default='')
|
||||
parser.add_argument('--api_conf', help='Api configuration parameters in coma separate keypairs. EX "user=admin,pass=pandora,api_pass=1234,api_url=http://test.artica.es/pandora_console/include/api.php"')
|
||||
parser.add_argument('--module_graph', help='Uses pandora API to generate a module graph and attach it to the alert needs module_id and interval parameters in coma separate keypairs. EX "module_id=55,interval=3600"')
|
||||
parser.add_argument('--tmp_dir', help='Temporary path to store grph images', default='/tmp')
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
### Functions:
|
||||
def parse_dic(cValues):
|
||||
"""convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """
|
||||
data={}
|
||||
try :
|
||||
for kv in cValues.split(","):
|
||||
k,v = kv.strip().split("=")
|
||||
data[k.strip()]=v.strip()
|
||||
except Exception as e :
|
||||
print(f"Warning, error parsing keypairs values: {e}")
|
||||
return data
|
||||
|
||||
def add_embed_itmes(data):
|
||||
"""iterate dictionary and set webhook fields, one for eacj keypair"""
|
||||
for k, v in data.items() :
|
||||
embed.add_embed_field(name=k, value=v)
|
||||
|
||||
def parse_api_conf(cConf):
|
||||
if args.api_conf :
|
||||
# Parse Api config
|
||||
print ("Api config enable")
|
||||
apid = parse_dic(cConf)
|
||||
|
||||
if apid.get("user") is None:
|
||||
print ("Error no user defined in api_conf keypairs, skiping graph generation.")
|
||||
return
|
||||
|
||||
if apid.get("pass") is None:
|
||||
print ("Error no password defined in api_conf keypairs, skiping graph generation.")
|
||||
return
|
||||
|
||||
if apid.get("api_pass") is None:
|
||||
print ("Error no Api pass defined in api_conf keypairs, skiping graph generation.")
|
||||
return
|
||||
|
||||
if apid.get("api_url") is None:
|
||||
apid['api_url'] = "http://127.0.0.1/pandora_console/include/api.php"
|
||||
#print(f"api_url: {apid['api_url']}")
|
||||
|
||||
return apid
|
||||
else:
|
||||
return None
|
||||
|
||||
def parse_graph_conf(cGraph):
|
||||
if not args.api_conf:
|
||||
print ("To get graph data api conf shoul be provided please set an api config")
|
||||
return
|
||||
|
||||
if cGraph :
|
||||
# Parse Api config
|
||||
graphd = parse_dic(cGraph)
|
||||
if graphd.get("module_id") is None:
|
||||
print ("error no module_id defined in module_graph keypairs, skiping graph generation.")
|
||||
return
|
||||
|
||||
if graphd.get("interval") is None:
|
||||
graphd["interval"] = 3600
|
||||
|
||||
return graphd
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_graph_by_moduleid (baseUrl,pUser, pPass, apiPass, moduleId, graphInterval) :
|
||||
sep="url_encode_separator_%7C"
|
||||
try:
|
||||
url = f"{baseUrl}?op=get&op2=module_graph&id={moduleId}&other={graphInterval}%7C1&other_mode={sep}C&apipass={apiPass}&api=1&user={pUser}&pass={pPass}"
|
||||
graph = requests.get(url)
|
||||
if graph.status_code != 200:
|
||||
print (f"Error requested api url, status code: {graph.status_code}. Skiping graph generation")
|
||||
return None
|
||||
if graph.text == "auth error":
|
||||
print (f"Error requested Pandora api url, status code: {graph.text}. Skiping graph generation")
|
||||
return None
|
||||
if graph.text == "Id does not exist in database.":
|
||||
print (f"Error requested Pandora api url, status code: {graph.text}. Skiping graph generation")
|
||||
return None
|
||||
except:
|
||||
print("Error requested api url. Skiping graph generation")
|
||||
return None
|
||||
|
||||
return graph
|
||||
|
||||
## Main
|
||||
## Basic message
|
||||
webhook = DiscordWebhook(url=args.url, content=args.message, avatar_url=args.avatar_url)
|
||||
# create embed object for webhook
|
||||
embed = DiscordEmbed(title=args.alert_tittle, description=args.alert_desc, color=int(args.tittle_color, 16))
|
||||
# set author
|
||||
embed.set_author(name=args.author, url=args.author_url, icon_url=args.author_icon_url)
|
||||
# set thumbnail
|
||||
if args.thumb: embed.set_thumbnail(url=args.thumb)
|
||||
# set footer
|
||||
if args.footer : embed.set_footer(text=args.footer)
|
||||
# set timestamp (default is now)
|
||||
embed.set_timestamp()
|
||||
# Parse data keys
|
||||
data = parse_dic(args.data)
|
||||
# add fields to embed
|
||||
add_embed_itmes(data)
|
||||
|
||||
# Parse api config
|
||||
api = parse_api_conf(args.api_conf)
|
||||
# Parse graph config
|
||||
graph_cfg = parse_graph_conf(args.module_graph)
|
||||
|
||||
## Generate module graph
|
||||
|
||||
if graph_cfg is not None and api is not None:
|
||||
graph = get_graph_by_moduleid (api["api_url"],api["user"], api["pass"], api["api_pass"], graph_cfg["module_id"], graph_cfg["interval"])
|
||||
|
||||
if graph is not None:
|
||||
try:
|
||||
namef = f"graph_{graph_cfg['module_id']}.{datetime.now().strftime('%s')}.png"
|
||||
filename = f"{args.tmp_dir}/{namef}"
|
||||
with open(filename, "wb") as f:
|
||||
f.write(b64decode(graph.text))
|
||||
f.close
|
||||
print (f"Graph generated on temporary file {filename}")
|
||||
except Exception as e :
|
||||
print(f"Error, cant generate graph file: {e}")
|
||||
filename = None
|
||||
|
||||
try:
|
||||
with open(filename, "rb") as F:
|
||||
webhook.add_file(file=F.read(), filename=namef)
|
||||
f.close
|
||||
embed.set_image(url=f'attachment://{namef}')
|
||||
except Exception as e :
|
||||
print(f"Error, cant add graph file: {e}")
|
||||
filename = None
|
||||
|
||||
# add embed object to webhook
|
||||
webhook.add_embed(embed)
|
||||
|
||||
# Execute webhook send
|
||||
response = webhook.execute()
|
||||
|
||||
# clean temp file if exist
|
||||
try:
|
||||
os.remove(filename)
|
||||
except:
|
||||
pass
|
||||
|
||||
# print response
|
||||
print (f"Message sent. status code: {response[0].status_code}") if response[0].status_code == 200 else print (f"Error status code: {response[0].status_code}")
|
|
@ -0,0 +1,6 @@
|
|||
certifi==2020.11.8
|
||||
chardet==3.0.4
|
||||
discord-webhook==0.11.0
|
||||
idna==2.10
|
||||
requests==2.24.0
|
||||
urllib3==1.25.11
|
|
@ -0,0 +1,19 @@
|
|||
#exetution example
|
||||
|
||||
python3 pandora_discord_cli.py -d "Agent=Server22,Module=test_module,Group=Servers,State=Critical,Data=22,Timestamp=2020-11-04 11:14:00" \
|
||||
-u https://discord.com/api/webhooks/702868786843353179/YI1LOUzC64EcYcpPVB_ \
|
||||
--tittle_color ed2512 \
|
||||
--footer "PandoraFMS Alert" \
|
||||
-A "Sauron Systems" \
|
||||
--author_icon_url "https://pandorafms.com/wp-content/uploads/2019/04/software-de-monitorizacion-pandorafms-logo.png" \
|
||||
-m "We have bad news for you. Something is on CRITICAL status 2" \
|
||||
--author_url https://pandorafms.com/ \
|
||||
-D "Module test is going to critical" \
|
||||
--thumb https://pandorafms.com/images/alerta_roja.png \
|
||||
--avatar_url https://pandorafms.com/images/alerta_roja.png \
|
||||
--api_conf "user=admin,pass=pandora,api_pass=pandora,api_url=http://192.168.80.222/pandora_console/include/api.php" \
|
||||
--module_graph "module_id=6266, interval=3600" \
|
||||
--tmp_dir /tmp
|
||||
|
||||
# Pandora FMS command definition example
|
||||
python3 /usr/share/pandora_server/util/pandora-discord/pandora_discord_cli.py -u "_field1_" -d "_field2_" -D "_field3_" --tittle_color _field4_ --thumb _field5_ --api_conf "_field6_" --module_graph "_field7_" -A "Pandora FMS Alert system" --footer "PandoraFMS" --author_icon_url "https://pandorafms.com/wp-content/uploads/2019/04/software-de-monitorizacion-pandorafms-logo.png" --author_url https://pandorafms.com/ --tmp_dir /tmp
|
|
@ -0,0 +1,111 @@
|
|||
import requests
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
### Variables and arg parser ###
|
||||
parser = argparse.ArgumentParser(description='Google chat webhook conector')
|
||||
parser.add_argument(
|
||||
'-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True)
|
||||
parser.add_argument(
|
||||
'-u', '--url', help='Google chat webhook URL', required=True)
|
||||
parser.add_argument('-t', '--alert_title', help='Alert title',
|
||||
default='PandoraFMS alert system')
|
||||
parser.add_argument('-D', '--alert_desc',
|
||||
help='Alert description', default='Alert Fired')
|
||||
parser.add_argument('--thumb', help='Custom thumbnail url',
|
||||
default="https://pandorafms.com/images/alerta_roja.png")
|
||||
parser.add_argument('--btn_desc', help='button description', default=None)
|
||||
parser.add_argument('--btn_url', help='button url',
|
||||
default="https://pandorafms.com/")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# classes
|
||||
|
||||
|
||||
class Message():
|
||||
def __init__(self, title, subtitle, imageurl='https://goo.gl/aeDtrS'):
|
||||
""" Initialize message object, setting header options"""
|
||||
self.dic = {
|
||||
'cards': []
|
||||
}
|
||||
|
||||
header = {'header': {'title': title,
|
||||
'subtitle': subtitle, 'imageUrl': imageurl}}
|
||||
self.dic['cards'].append(header)
|
||||
|
||||
sections = {'sections': []}
|
||||
self.dic['cards'].append(sections)
|
||||
|
||||
def add_header(self, title, subtitle, imageurl='https://goo.gl/aeDtrS'):
|
||||
"""Add header to message object"""
|
||||
header = {'header': {'title': title,
|
||||
'subtitle': subtitle, 'imageUrl': imageurl}}
|
||||
self.dic['cards'].append(header)
|
||||
|
||||
def add_value(self, keyval):
|
||||
"""Add key value pairs data to message object, keyval should be a dictionary"""
|
||||
m = ''
|
||||
arr = []
|
||||
for k, v in keyval.items():
|
||||
m += f"<b>{k}</b>: {v} \n"
|
||||
|
||||
arr.append({'textParagraph': {'text': m}})
|
||||
|
||||
widgets = {'widgets': arr}
|
||||
self.dic['cards'][1]['sections'].append(widgets)
|
||||
|
||||
def add_buttom(self, desc, url):
|
||||
"""Add button to message object"""
|
||||
btn = [{"textButton": {"text": desc, "onClick": {"openLink": {'url': url}}}}]
|
||||
arr = [({'buttons': btn})]
|
||||
|
||||
widgets = {'widgets': arr}
|
||||
self.dic['cards'][1]['sections'].append(widgets)
|
||||
|
||||
# functions
|
||||
|
||||
|
||||
def parse_dic(cValues):
|
||||
"""convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """
|
||||
data = {}
|
||||
try:
|
||||
for kv in cValues.split(","):
|
||||
k, v = kv.strip().split("=")
|
||||
data[k.strip()] = v.strip()
|
||||
except Exception as e:
|
||||
print(f"Warning, error parsing keypairs values: {e}")
|
||||
return data
|
||||
|
||||
|
||||
def sendMessage(url, message):
|
||||
"""sends google chat message"""
|
||||
message = json.dumps(message)
|
||||
try:
|
||||
header = {'Content-Type': 'application/json; charset: UTF-8'}
|
||||
response = requests.post(url, headers=header, data=message)
|
||||
|
||||
print(f"Mesage sent succefuly: {response.status_code}")
|
||||
except:
|
||||
print("Error requested api url. Skiping graph generation")
|
||||
return None
|
||||
return response
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Initializaate message object
|
||||
a = Message(args.alert_title, args.alert_desc, args.thumb)
|
||||
# Parse data values
|
||||
data = parse_dic(args.data)
|
||||
# Add datavalues into message object
|
||||
a.add_value(data)
|
||||
# Chek button parameters and add it to the message object
|
||||
if args.btn_desc != None:
|
||||
a.add_buttom(args.btn_desc, args.btn_url)
|
||||
|
||||
# Send message
|
||||
sendMessage(args.url, a.dic)
|
|
@ -0,0 +1,5 @@
|
|||
certifi==2020.12.5
|
||||
chardet==3.0.4
|
||||
idna==2.10
|
||||
requests==2.25.0
|
||||
urllib3==1.26.2
|
|
@ -0,0 +1,14 @@
|
|||
#exetution example
|
||||
|
||||
python3 pandora-gchat-cli.py \
|
||||
-d 'Agent=Server22,Module=test_module,Group=Servers,State=Critical,Data=22,Timestamp=2020-11-04 11:14:00' \
|
||||
-u https://chat.googleapis.com/v1/spaces/AAAA6-AOZQ8/messages\?key\=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI\&token\=_ZGwKN4lue8ZiDKGVMLfMay3hLRrYjmgYr2fXPqPy0c%3D \
|
||||
-t 'PandoraFMS Alert' \
|
||||
-D 'Alert Fired' \
|
||||
--thumb https://pandorafms.com/images/alerta_roja.png \
|
||||
--btn_desc pandorafms.com \
|
||||
--btn_url https://pandorafms.com/
|
||||
|
||||
|
||||
# Pandora FMS command definition example
|
||||
python3 /usr/share/pandora_server/util/pandora-gchat/pandora-gchat-cli.py -d '_field1_' -u '_field2_' -t '_field3_' -D '_field4_' --thumb '_field5_' --btn_desc pandorafms.com --btn_url https://pandorafms.com/
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse, pymsteams
|
||||
|
||||
parser = argparse.ArgumentParser(description='MS Teams connector')
|
||||
parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True)
|
||||
parser.add_argument('-u', '--url', help='Teams webhook URL', required=True)
|
||||
parser.add_argument('-t', '--alert_tittle', help='Alert tittle', default='PandoraFMS alert fired')
|
||||
parser.add_argument('-D', '--alert_desc', help='Alert description', default='Alert Fired')
|
||||
parser.add_argument('-m', '--message', help='Alert message', default='')
|
||||
parser.add_argument('-T','--tittle_color', help='Alert tittle descripcion in HEX EX: 53e514', default="ff0000")
|
||||
parser.add_argument('--sub_desc', help='Alert sub description', default='Alert Fired')
|
||||
parser.add_argument('--thumb', help='Custom thumbnail url', default="https://pandorafms.com/images/alerta_roja.png")
|
||||
parser.add_argument('--button', help='Pandora button Url', default='https://pandorafms.com')
|
||||
parser.add_argument('--button_desc', help='Pandora button description', default='Open web console')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
### Functions:
|
||||
def parse_dic(cValues):
|
||||
"""convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """
|
||||
data={}
|
||||
try :
|
||||
for kv in cValues.split(","):
|
||||
k,v = kv.strip().split("=")
|
||||
data[k.strip()]=v.strip()
|
||||
except Exception as e :
|
||||
print(f"Warning, error parsing keypairs values: {e}")
|
||||
return data
|
||||
|
||||
def add_embed_itmes(data):
|
||||
"""iterate dictionary and set webhook fields, one for eacj keypair"""
|
||||
for k, v in data.items() :
|
||||
myMessageSection.addFact(f"{k}:", v)
|
||||
|
||||
##Main
|
||||
|
||||
# You must create the connectorcard object with the Microsoft Webhook URL
|
||||
myTeamsMessage = pymsteams.connectorcard(args.url)
|
||||
|
||||
# Set Summary
|
||||
myTeamsMessage.summary('Pandora FMS')
|
||||
|
||||
# Set Alert tittle
|
||||
myTeamsMessage.title(args.alert_tittle)
|
||||
|
||||
# Set link buttom
|
||||
myTeamsMessage.addLinkButton(args.button_desc, args.button)
|
||||
|
||||
# Set message color
|
||||
myTeamsMessage.color(args.tittle_color)
|
||||
|
||||
# create the section
|
||||
myMessageSection = pymsteams.cardsection()
|
||||
|
||||
# Section Title
|
||||
myMessageSection.title(args.message)
|
||||
|
||||
# Activity Elements
|
||||
myMessageSection.activityTitle(args.alert_desc)
|
||||
myMessageSection.activitySubtitle(args.sub_desc)
|
||||
myMessageSection.activityImage(args.thumb)
|
||||
|
||||
# Facts are key value pairs displayed in a list.
|
||||
data = parse_dic(args.data)
|
||||
add_embed_itmes(data)
|
||||
|
||||
# Section Text
|
||||
# myMessageSection.text("This is my section text")
|
||||
|
||||
# Section Images
|
||||
# myMessageSection.addImage("http://i.imgur.com/c4jt321l.png", ititle="This Is Fine")
|
||||
|
||||
# Add your section to the connector card object before sending
|
||||
myTeamsMessage.addSection(myMessageSection)
|
||||
|
||||
# Then send the card
|
||||
try:
|
||||
myTeamsMessage.send()
|
||||
except Exception as e :
|
||||
exit(f"Error sending to message: {e}")
|
||||
|
||||
print (f"Mesage sent succefuly: {myTeamsMessage.last_http_status}")
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse, pymsteams
|
||||
|
||||
parser = argparse.ArgumentParser(description='MsTeams connector')
|
||||
parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True)
|
||||
parser.add_argument('-u', '--url', help='Teams webhook URL', required=True)
|
||||
parser.add_argument('-t', '--alert_tittle', help='Alert tittle', default='PandoraFMS alert fired')
|
||||
parser.add_argument('-D', '--alert_desc', help='Alert description', default='Alert Fired')
|
||||
parser.add_argument('-m', '--message', help='Alert message', default='')
|
||||
parser.add_argument('-T','--tittle_color', help='Alert tittle descripcion in HEX EX: 53e514', default="53e514")
|
||||
parser.add_argument('--sub_desc', help='Alert sub description', default='Alert Fired')
|
||||
parser.add_argument('--thumb', help='Custom thumbnail url', default="https://pandorafms.com/images/alerta_roja.png")
|
||||
parser.add_argument('--button', help='Pandora button Url', default='https://pandorafms.com')
|
||||
parser.add_argument('--button_desc', help='Pandora button description', default='Open web console')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
### Functions:
|
||||
def parse_dic(cValues):
|
||||
"""convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """
|
||||
data={}
|
||||
try :
|
||||
for kv in cValues.split(","):
|
||||
k,v = kv.strip().split("=")
|
||||
data[k.strip()]=v.strip()
|
||||
except Exception as e :
|
||||
print(f"Warning, error parsing keypairs values: {e}")
|
||||
return data
|
||||
|
||||
def add_embed_itmes(data):
|
||||
"""iterate dictionary and set webhook fields, one for eacj keypair"""
|
||||
for k, v in data.items() :
|
||||
myMessageSection.addFact(f"{k}:", v)
|
||||
|
||||
##Main
|
||||
|
||||
# You must create the connectorcard object with the Microsoft Webhook URL
|
||||
myTeamsMessage = pymsteams.connectorcard(args.url)
|
||||
|
||||
# Set Summary
|
||||
myTeamsMessage.summary(args.message)
|
||||
|
||||
# Set Alert tittle
|
||||
myTeamsMessage.title(args.alert_tittle)
|
||||
|
||||
# Set link buttom
|
||||
myTeamsMessage.addLinkButton(args.button_desc, args.button)
|
||||
|
||||
# Set message color
|
||||
myTeamsMessage.color(args.tittle_color)
|
||||
|
||||
# create the section
|
||||
myMessageSection = pymsteams.cardsection()
|
||||
|
||||
# Section Title
|
||||
myMessageSection.title(args.message)
|
||||
|
||||
# Activity Elements
|
||||
myMessageSection.activityTitle(args.alert_desc)
|
||||
myMessageSection.activitySubtitle(args.sub_desc)
|
||||
myMessageSection.activityImage(args.thumb)
|
||||
|
||||
# Facts are key value pairs displayed in a list.
|
||||
data = parse_dic(args.data)
|
||||
add_embed_itmes(data)
|
||||
|
||||
# Section Text
|
||||
# myMessageSection.text("This is my section text")
|
||||
|
||||
# Section Images
|
||||
# myMessageSection.addImage("http://i.imgur.com/c4jt321l.png", ititle="This Is Fine")
|
||||
|
||||
# Add your section to the connector card object before sending
|
||||
myTeamsMessage.addSection(myMessageSection)
|
||||
|
||||
# Then send the card
|
||||
try:
|
||||
myTeamsMessage.send()
|
||||
except Exception as e :
|
||||
print(f"Error sending to message: {e}")
|
|
@ -0,0 +1,6 @@
|
|||
certifi==2020.11.8
|
||||
chardet==3.0.4
|
||||
idna==2.10
|
||||
pymsteams==0.1.14
|
||||
requests==2.25.0
|
||||
urllib3==1.26.2
|
|
@ -0,0 +1,15 @@
|
|||
#exetution example
|
||||
|
||||
python3 pandora-teams-cli.py -d "Agent=Server22,Module=test_module,Group=Servers,State=Critical,Data=22,Timestamp=2020-11-04 11:14:00" \
|
||||
-u https://outlook.office.com/webhook/6f819e54-9c3f-4f87-94f4-90159496ef12@b3b55021-a812-46af-a5ef-127cc662d5b7/IncomingWebhook/634dafb7fe6549c9a214dd7fa9b97416/76c50d52-8678-49c2-9279-9f7bb3bb5a07 \
|
||||
-t "Alert Tittle" \
|
||||
-D "Alert description" \
|
||||
-m "Pandora FMS Alert message" \
|
||||
-T 53e514 \
|
||||
--sub_desc "Alert subdescription" \
|
||||
--thumb "https://pandorafms.com/images/alerta_roja.png" \
|
||||
--button https://pandorafms.com \
|
||||
--button_desc "Open PandoraFMS"
|
||||
|
||||
# Pandora FMS command definition example
|
||||
python3 /usr/share/pandora_server/util/pandora-teams/pandora-msteams-cli.py -d "_field1_" -u "_field2_" -t "_field3_" -D "_field4_" -m "_field5_" -T _field6_ --sub_desc "_field7_" --thumb "_field8_" --button http://newfork.artica.es/pandora_console/ --button_desc "Open PandoraFMS Console"
|
|
@ -0,0 +1 @@
|
|||
venv
|
|
@ -0,0 +1,177 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import requests, argparse, sys, os
|
||||
from slack_sdk import WebClient
|
||||
from slack_sdk.errors import SlackApiError
|
||||
from datetime import datetime
|
||||
from re import search
|
||||
from base64 import b64decode
|
||||
|
||||
|
||||
|
||||
### Variables and arg parser ###
|
||||
parser = argparse.ArgumentParser(description='Slack BOT APP conector')
|
||||
parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True)
|
||||
parser.add_argument('-t', '--token', help='BOT Token', required=True)
|
||||
parser.add_argument('-c', '--channel', help='Slack channel id/name', required=True)
|
||||
parser.add_argument('-e', '--emoji', help='Slack emoji for tittle, default: :red_circle:', default=':red_circle:')
|
||||
parser.add_argument('-T', '--tittle', help='Alert tittle, default: PandoraFMS alert', default='PandoraFMS alert')
|
||||
parser.add_argument('-D', '--desc', help='Slack description message', default='')
|
||||
parser.add_argument('-F','--footer', help='Custom footer, default: PandoraFMS', default='PandoraFMS')
|
||||
parser.add_argument('--api_conf', help='Api configuration parameters in coma separate keypairs. EX "user=admin,pass=pandora,api_pass=1234,api_url=http://test.artica.es/pandora_console/include/api.php"')
|
||||
parser.add_argument('--module_graph', help='Uses pandora API to generate a module graph and attach it to the alert needs module_id and interval parameters in coma separate keypairs. EX "module_id=55,interval=3600"')
|
||||
parser.add_argument('--tmp_dir', help='Temporary path to store grph images', default='/tmp')
|
||||
|
||||
args = parser.parse_args()
|
||||
filename = None
|
||||
|
||||
#Functions
|
||||
|
||||
def parse_dic(cValues):
|
||||
"""convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """
|
||||
data={}
|
||||
try :
|
||||
for kv in cValues.split(","):
|
||||
k,v = kv.strip().split("=")
|
||||
data[k.strip()]=v.strip()
|
||||
except Exception as e :
|
||||
print(f"Warning, error parsing keypairs values: {e}")
|
||||
return data
|
||||
|
||||
def compose_message (values, tittle, emoji, message, footer):
|
||||
"""Format Text"""
|
||||
values = parse_dic(values)
|
||||
m = f"{emoji} *{tittle}*\n_{message}_\n\n"
|
||||
|
||||
for k, v in values.items() :
|
||||
m += f"*{k}* : {v}\n"
|
||||
return m
|
||||
|
||||
def parse_api_conf(cConf):
|
||||
"""Check apiconfiguration parameters """
|
||||
if args.api_conf :
|
||||
# Parse Api config
|
||||
print ("Api config enable")
|
||||
apid = parse_dic(cConf)
|
||||
|
||||
if apid.get("user") is None:
|
||||
print ("Warning. no user defined in api_conf keypairs, skiping graph generation.")
|
||||
return None
|
||||
|
||||
if apid.get("pass") is None:
|
||||
print ("Warning. no password defined in api_conf keypairs, skiping graph generation.")
|
||||
return None
|
||||
|
||||
if apid.get("api_pass") is None:
|
||||
print ("Warning. no api pass defined in api_conf keypairs, skiping graph generation.")
|
||||
return None
|
||||
|
||||
if apid.get("api_url") is None:
|
||||
apid['api_url'] = "http://127.0.0.1/pandora_console/include/api.php"
|
||||
#print(f"api_url: {apid['api_url']}")
|
||||
|
||||
return apid
|
||||
else:
|
||||
return None
|
||||
|
||||
def parse_graph_conf(cGraph):
|
||||
"""Check module graph parameters """
|
||||
if cGraph :
|
||||
# Parse Api config
|
||||
graphd = parse_dic(cGraph)
|
||||
if graphd.get("module_id") is None:
|
||||
print ("Warning. no module_id defined in module_graph keypairs, skiping graph generation.")
|
||||
return
|
||||
|
||||
if graphd.get("interval") is None:
|
||||
graphd["interval"] = 3600
|
||||
|
||||
return graphd
|
||||
else:
|
||||
print("Warning. no module_graph keypairs defined, skiping graph generation")
|
||||
return None
|
||||
|
||||
def get_graph_by_moduleid (baseUrl,pUser, pPass, apiPass, moduleId, graphInterval, sep="url_encode_separator_%7C") :
|
||||
"""Call Pandorafms api to get graph"""
|
||||
try:
|
||||
url = f"{baseUrl}?op=get&op2=module_graph&id={moduleId}&other={graphInterval}%7C1&other_mode={sep}C&apipass={apiPass}&api=1&user={pUser}&pass={pPass}"
|
||||
graph = requests.get(url)
|
||||
if graph.status_code != 200:
|
||||
print (f"Error requested api url, status code: {graph.status_code}. Skiping graph generation")
|
||||
return None
|
||||
if graph.text == "auth error":
|
||||
print (f"Error requested Pandora api url, status code: {graph.text}. Skiping graph generation")
|
||||
return None
|
||||
if graph.text == "Id does not exist in database.":
|
||||
print (f"Error requested Pandora api url, status code: {graph.text}. Skiping graph generation")
|
||||
return None
|
||||
|
||||
except:
|
||||
print("Error requested api url. Skiping graph generation")
|
||||
return None
|
||||
return graph
|
||||
|
||||
def send_message(message, channel, client, feddback=None):
|
||||
"""Send text message as slack bot"""
|
||||
try:
|
||||
response = client.chat_postMessage(channel=channel, text=message)
|
||||
assert response["message"]["text"] == message
|
||||
if feddback is not None: print(feddback)
|
||||
except SlackApiError as e:
|
||||
# You will get a SlackApiError if "ok" is False
|
||||
assert e.response["ok"] is False
|
||||
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'
|
||||
print(f"Got an Slack auth error: {e.response['error']}")
|
||||
exit()
|
||||
|
||||
def send_image(imagepath, channel, client) :
|
||||
"""Send file as slack bot"""
|
||||
try:
|
||||
response = client.files_upload(channels=channel, file=imagepath)
|
||||
assert response["file"] # the uploaded file
|
||||
except SlackApiError as e:
|
||||
# You will get a SlackApiError if "ok" is False
|
||||
assert e.response["ok"] is False
|
||||
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'
|
||||
print(f"File Got an error: {e.response['error']}")
|
||||
|
||||
# Main
|
||||
# Intance the client object
|
||||
client = WebClient(token=args.token)
|
||||
# Compose message
|
||||
messageString = compose_message(args.data, args.tittle, args.emoji, args.desc, args.footer)
|
||||
|
||||
# Parse api config
|
||||
if args.api_conf :
|
||||
api = parse_api_conf(args.api_conf)
|
||||
# Parse graph config
|
||||
if api is not None:
|
||||
graph_cfg = parse_graph_conf(args.module_graph)
|
||||
|
||||
## Generate graph
|
||||
if graph_cfg is not None :
|
||||
graph = get_graph_by_moduleid (api["api_url"],api["user"], api["pass"], api["api_pass"], graph_cfg["module_id"], graph_cfg["interval"])
|
||||
|
||||
if graph is not None:
|
||||
try:
|
||||
filename = f"{args.tmp_dir}/graph_{graph_cfg['module_id']}.{datetime.now().strftime('%s')}.png"
|
||||
with open(filename, "wb") as f:
|
||||
f.write(b64decode(graph.text))
|
||||
f.close
|
||||
print (f"Graph generated on temporary file {filename}")
|
||||
except Exception as e :
|
||||
print(f"Error, cant generate graph file: {e}")
|
||||
filename = None
|
||||
else: filename = None
|
||||
|
||||
# Send message
|
||||
send_message(messageString, args.channel, client, "> Mesage sent succefuly")
|
||||
if filename is not None:
|
||||
if os.path.isfile(filename): send_image(filename, args.channel, client)
|
||||
if args.footer: send_message(args.footer, args.channel, client)
|
||||
|
||||
try:
|
||||
os.remove(filename)
|
||||
except:
|
||||
exit()
|
|
@ -0,0 +1,6 @@
|
|||
certifi==2020.11.8
|
||||
chardet==3.0.4
|
||||
idna==2.10
|
||||
requests==2.24.0
|
||||
slack-sdk==3.0.0
|
||||
urllib3==1.25.11
|
|
@ -0,0 +1,14 @@
|
|||
#exetution example
|
||||
|
||||
python3 pandora-slack-cli.py -d "Agent=Server22,Module=test_module,Group=Servers,State=Critical,Data=22,Timestamp=2020-11-04 11:14:00" \
|
||||
-t xoxb-1506287138481-1518221486533-V3QVzyBbS6lQnTKdfrdwCqYI \
|
||||
-c "varios" \
|
||||
-e ":red_circle:" \
|
||||
-T "PandoraFMS alert" \
|
||||
-D "El agente x esta en estado critico" \
|
||||
-F "Pandora FMS" \
|
||||
--api_conf "user=admin,pass=pandora,api_pass=pandora,api_url=http://192.168.80.43/pandora_console/include/api.php" \
|
||||
--module_graph "module_id=62, interval=3600" --tmp_dir /tmp
|
||||
|
||||
# Pandora FMS command definition example
|
||||
python3 /usr/share/pandora_server/util/pandora-slack/pandora-slack-cli.py -d "_field1_" -t _field2_ -c "_field3_" -e "_field4_" -T "_field5_" -D "_field6_" -F "Pandora FMS" --api_conf "_field7_" --module_graph "_field8_" --tmp_dir /tmp
|
|
@ -0,0 +1,27 @@
|
|||
import requests, argparse, json, sys, os
|
||||
|
||||
### Variables and arg parser ###
|
||||
parser = argparse.ArgumentParser(description='Bot telegram cli')
|
||||
parser.add_argument('-m', '--message', help='Message to be send', required=True)
|
||||
parser.add_argument('-t', '--token', help='Bot token', required=True)
|
||||
parser.add_argument('-c', '--chat_id', help='chat id to send messages', required=True)
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
def send(mssg, chatId, token):
|
||||
url = f"https://api.telegram.org/bot{token}/sendMessage"
|
||||
headers = {'content-type': 'application/json'}
|
||||
|
||||
data = {
|
||||
"chat_id": chatId,
|
||||
"text": mssg
|
||||
}
|
||||
|
||||
response = requests.get(url, data=json.dumps(data), headers=headers)
|
||||
|
||||
r = response.json()
|
||||
print(r)
|
||||
|
||||
send(mssg=args.message, chatId=args.chat_id, token=args.token)
|
|
@ -0,0 +1,5 @@
|
|||
certifi==2020.11.8
|
||||
chardet==3.0.4
|
||||
idna==2.10
|
||||
requests==2.24.0
|
||||
urllib3==1.25.11
|
|
@ -0,0 +1,6 @@
|
|||
#exetution example
|
||||
|
||||
python3 pandora-telegram-cli.py -t 1412764845:AAG-OxOKISOXwhITLFFNm6oq5YD2KI72fTQ -c -432610056 -m "Testing pandora telegram cli"
|
||||
|
||||
# Pandora FMS command definition example
|
||||
python3 pandora-telegram-cli.py -t _field1_ -c _field2_ -m" _field3_"
|
Loading…
Reference in New Issue