Initial code
Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
fe478845f3
commit
d38907dc35
6 changed files with 251 additions and 1 deletions
29
.pre-commit-config.yaml
Normal file
29
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: master
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-merge-conflict
|
||||
- id: double-quote-string-fixer
|
||||
- id: end-of-file-fixer
|
||||
- id: fix-encoding-pragma
|
||||
args: ['--remove']
|
||||
- id: requirements-txt-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: master
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ['--max-line-length=120']
|
||||
- repo: https://github.com/FalconSocial/pre-commit-python-sorter
|
||||
rev: master
|
||||
hooks:
|
||||
- id: python-import-sorter
|
||||
args: ['--silent-overwrite']
|
||||
- repo: https://github.com/chewse/pre-commit-mirrors-pydocstyle
|
||||
rev: master
|
||||
hooks:
|
||||
- id: pydocstyle
|
||||
args: ['--config=.pydocstyle', '--match="(?!test_).*\.py"']
|
||||
- repo: https://github.com/jumanjihouse/pre-commit-hooks
|
2
.pydocstyle
Normal file
2
.pydocstyle
Normal file
|
@ -0,0 +1,2 @@
|
|||
[pydocstyle]
|
||||
ignore = D100,D104,D400,D203,D204,D101,D213,D202
|
58
README.md
58
README.md
|
@ -1,2 +1,58 @@
|
|||
# notify-by-telegram
|
||||
Send Nagios notifications to a Telegram channel
|
||||
Send Nagios notifications to a Telegram channel.
|
||||
|
||||
|
||||
## Telegram bot
|
||||
|
||||
This [tutorial](https://takersplace.de/2019/12/19/telegram-notifications-with-nagios/) explains how to create a Telegram bot. You'll need the *chat_id* and *auth_key* for the next section.
|
||||
|
||||
## Installation
|
||||
|
||||
_This guide has been written for [Debian](https://www.debian.org/). Some commands might slightly change depending on your distribution._
|
||||
|
||||
Clone the repository:
|
||||
```
|
||||
git clone https://github.com/jouir/notify-by-telegram.git
|
||||
sudo cp -p notify-by-telegram.py /usr/lib/nagios/plugins/notify-by-telegram.py
|
||||
sudo chmod 755 /usr/lib/nagios/plugins/notify-by-telegram.py
|
||||
sudo chown root:root /usr/lib/nagios/plugins/notify-by-telegram.py
|
||||
```
|
||||
|
||||
Install dependencies using the package manager:
|
||||
```
|
||||
sudo apt install python3-jinja2 python3-requests
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Copy and update the configuration file example:
|
||||
```
|
||||
sudo cp -p config.json.example /etc/nagios/telegram.json
|
||||
sudo chmod 640 root:nagios /etc/nagios/telegram.json
|
||||
```
|
||||
|
||||
Add Nagios configurations:
|
||||
```
|
||||
sudo cp -p nagios.cfg /etc/nagios4/conf.d/telegram.cfg
|
||||
```
|
||||
|
||||
Ensure Nagios reads the configuration file:
|
||||
```
|
||||
grep cfg_dir=/etc/nagios4/conf.d /etc/nagios4/nagios.cfg
|
||||
```
|
||||
|
||||
Then reload service:
|
||||
```
|
||||
systemctl reload nagios4
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
Errors logs can be set with the `--logfile` argument.
|
||||
|
||||
Example:
|
||||
```
|
||||
tail -f /var/log/nagios4/telegram.log
|
||||
```
|
||||
|
||||
Log level can be raised using `--verbose` or even more with `--debug` arguments.
|
||||
|
|
4
config.json.example
Normal file
4
config.json.example
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"chat_id": 99,
|
||||
"auth_key": "hash"
|
||||
}
|
9
nagios.cfg
Normal file
9
nagios.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
define command {
|
||||
command_name notify-host-by-telegram
|
||||
command_line /usr/lib/nagios/plugins/notify-by-telegram.py -c /etc/nagios/telegram.json --logfile /var/log/nagios4/telegram.log host --notification-type "$NOTIFICATIONTYPE$" --service-desc "$SERVICEDESC$" --host-name "$HOSTNAME$" --host-state "$HOSTSTATE$" --host-address "$HOSTADDRESS$" --host-output "$HOSTOUTPUT$" --long-date-time "$LONGDATETIME$"
|
||||
}
|
||||
|
||||
define command {
|
||||
command_name notify-service-by-telegram
|
||||
command_line /usr/lib/nagios/plugins/notify-by-telegram.py -c /etc/nagios/telegram.json --logfile /var/log/nagios4/telegram.log service --notification-type "$NOTIFICATIONTYPE$" --service-desc "$SERVICEDESC$" --host-alias "$HOSTALIAS$" --host-address "$HOSTADDRESS$" --service-state "$SERVICESTATE$" --long-date-time "$LONGDATETIME$" --service-output "$SERVICEOUTPUT$"
|
||||
}
|
150
notify-by-telegram.py
Executable file
150
notify-by-telegram.py
Executable file
|
@ -0,0 +1,150 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
import requests
|
||||
from jinja2 import Template
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InvalidConfigException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser()
|
||||
# base arguments
|
||||
parser.add_argument('-v', '--verbose', dest='loglevel', action='store_const', const=logging.INFO,
|
||||
help='Print more output')
|
||||
parser.add_argument('-d', '--debug', dest='loglevel', action='store_const', const=logging.DEBUG,
|
||||
default=logging.WARNING, help='Print even more output')
|
||||
parser.add_argument('-c', '--config', help='Configuration file location', required=True)
|
||||
parser.add_argument('-o', '--logfile', help='Logging file location')
|
||||
subparsers = parser.add_subparsers(title='commands', dest='command', help='Nagios notification type')
|
||||
|
||||
# host notifications
|
||||
host_parser = subparsers.add_parser('host')
|
||||
host_parser.add_argument('--notification-type', help='Nagios $NOTIFICATIONTYPE$', required=True)
|
||||
host_parser.add_argument('--service-desc', help='Nagios $SERVICEDESC$', required=True)
|
||||
host_parser.add_argument('--host-name', help='Nagios $HOSTNAME$', required=True)
|
||||
host_parser.add_argument('--host-state', help='Nagios $HOSTSTATE$', required=True)
|
||||
host_parser.add_argument('--host-address', help='Nagios $HOSTADDRESS$', required=True)
|
||||
host_parser.add_argument('--host-output', help='Nagios $HOSTOUTPUT$', required=True)
|
||||
host_parser.add_argument('--long-date-time', help='Nagios $LONGDATETIME$', required=True)
|
||||
|
||||
# service notifications
|
||||
service_parser = subparsers.add_parser('service')
|
||||
service_parser.add_argument('--notification-type', help='Nagios $NOTIFICATIONTYPE$', required=True)
|
||||
service_parser.add_argument('--service-desc', help='Nagios $SERVICEDESC$', required=True)
|
||||
service_parser.add_argument('--host-alias', help='Nagios $HOSTALIAS$', required=True)
|
||||
service_parser.add_argument('--host-address', help='Nagios $HOSTADDRESS$', required=True)
|
||||
service_parser.add_argument('--service-state', help='Nagios $SERVICESTATE$', required=True)
|
||||
service_parser.add_argument('--long-date-time', help='Nagios $LONGDATETIME$', required=True)
|
||||
service_parser.add_argument('--service-output', help='Nagios $SERVICEOUTPUT$', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def read_config(filename=None):
|
||||
if filename and os.path.isfile(filename):
|
||||
with open(filename, 'r') as fd:
|
||||
return json.load(fd)
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def validate_config(config):
|
||||
if config is None:
|
||||
raise InvalidConfigException('Config is not a dict')
|
||||
for key in ['chat_id', 'auth_key']:
|
||||
if key not in config:
|
||||
raise InvalidConfigException(f'Missing "{key}" key in config')
|
||||
|
||||
|
||||
def setup_logging(args):
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=args.loglevel, filename=args.logfile)
|
||||
|
||||
|
||||
def markdown_escape(text):
|
||||
for special_char in ['\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '#', '+', '-', '.', '!']:
|
||||
text = text.replace(special_char, fr'\{special_char}')
|
||||
return text
|
||||
|
||||
|
||||
def generate_host_payload(chat_id, args):
|
||||
payload = {'chat_id': chat_id, 'parse_mode': 'MarkdownV2'}
|
||||
text = r"""\*\*\*\*\* Nagios \*\*\*\*\*
|
||||
*Notification Type:* {{notification_type}}
|
||||
*Host:* {{host_name}}
|
||||
*State:* {{host_state}}
|
||||
*Address:* {{host_address}}
|
||||
*Info:* {{host_output}}
|
||||
*Date/Time:* {{long_date_time}}
|
||||
"""
|
||||
template = Template(text)
|
||||
text = template.render(notification_type=markdown_escape(args.notification_type),
|
||||
host_name=markdown_escape(args.host_name), host_state=markdown_escape(args.host_state),
|
||||
host_address=markdown_escape(args.host_address),
|
||||
host_output=markdown_escape(args.host_output),
|
||||
long_date_time=markdown_escape(args.long_date_time))
|
||||
payload['text'] = text
|
||||
return payload
|
||||
|
||||
|
||||
def generate_service_payload(chat_id, args):
|
||||
payload = {'chat_id': chat_id, 'parse_mode': 'MarkdownV2'}
|
||||
text = r"""\*\*\*\*\* Nagios \*\*\*\*\*
|
||||
*Notification Type:* {{notification_type}}
|
||||
*Service:* {{service_desc}}
|
||||
*Host:* {{host_alias}}
|
||||
*Address:* {{host_address}}
|
||||
*State:* {{service_state}}
|
||||
*Date/Time:* {{long_date_time}}
|
||||
*Additional Info:*
|
||||
{{service_output}}
|
||||
"""
|
||||
template = Template(text)
|
||||
text = template.render(notification_type=markdown_escape(args.notification_type),
|
||||
service_desc=markdown_escape(args.service_desc), host_alias=markdown_escape(args.host_alias),
|
||||
host_address=markdown_escape(args.host_address),
|
||||
service_state=markdown_escape(args.service_state),
|
||||
long_date_time=markdown_escape(args.long_date_time),
|
||||
service_output=markdown_escape(args.service_output))
|
||||
payload['text'] = text
|
||||
return payload
|
||||
|
||||
|
||||
def send_message(auth_key, payload):
|
||||
r = requests.post(f'https://api.telegram.org/bot{auth_key}/sendMessage', json=payload)
|
||||
if r.status_code != requests.codes.ok:
|
||||
description = r.json().get('description')
|
||||
logger.error(f'{r.status_code}: {description}')
|
||||
logger.debug(payload)
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
setup_logging(args)
|
||||
logger.info(f'reading configuration file {args.config}')
|
||||
config = read_config(args.config)
|
||||
logger.info('validating configuration')
|
||||
validate_config(config)
|
||||
|
||||
logger.info('generating payload')
|
||||
if args.command == 'host':
|
||||
payload = generate_host_payload(chat_id=config['chat_id'], args=args)
|
||||
elif args.command == 'service':
|
||||
payload = generate_service_payload(chat_id=config['chat_id'], args=args)
|
||||
else:
|
||||
raise NotImplementedError(f'Command {args.command} not supported')
|
||||
|
||||
logger.info('sending message to telegram api')
|
||||
send_message(auth_key=config['auth_key'], payload=payload)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue