Browse Source
Multiple changes:
Multiple changes:
1) Makes mixin for API views. 2) Makes device monitoring notification. And little bit fixesdevel
16 changed files with 332 additions and 60 deletions
-
68agent/monitoring_agent.py
-
7chatbot/telebot.py
-
2devapp/forms.py
-
44devapp/locale/ru/LC_MESSAGES/django.po
-
34devapp/migrations/0006_auto_20180129_1625.py
-
17devapp/models.py
-
6devapp/templates/devapp/add_dev.html
-
2devapp/templates/devapp/dev.html
-
20devapp/templates/devapp/devices.html
-
6devapp/urls.py
-
112devapp/views.py
-
57djing/global_base_views.py
-
6djing/settings.py
-
4djing/views.py
-
1requirements.txt
-
6taskapp/handle.py
@ -0,0 +1,68 @@ |
|||
#!/usr/bin/env python3 |
|||
import sys |
|||
import re |
|||
from hashlib import sha256 |
|||
import requests |
|||
|
|||
API_AUTH_SECRET = 'asihdfaoisydoiayosidyaoisydoiasydaisydasd' |
|||
|
|||
SERVER_DOMAIN = 'http://localhost:8000' |
|||
|
|||
|
|||
IP_REGEXP = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \ |
|||
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \ |
|||
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \ |
|||
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' |
|||
|
|||
|
|||
def calc_hash(data): |
|||
if type(data) is str: |
|||
result_data = data.encode('utf-8') |
|||
else: |
|||
result_data = bytes(data) |
|||
return sha256(result_data).hexdigest() |
|||
|
|||
|
|||
def check_sign(get_list, sign): |
|||
hashed = '_'.join(get_list) |
|||
my_sign = calc_hash(hashed) |
|||
return sign == my_sign |
|||
|
|||
|
|||
def validate(regexp, string): |
|||
if not bool(re.match(regexp, string)): |
|||
raise ValueError |
|||
return string |
|||
|
|||
|
|||
def validate_status(text): |
|||
if not text in ('UP', 'DOWN', 'UNREACHABLE'): |
|||
raise ValueError |
|||
return text |
|||
|
|||
|
|||
def send_request(ip, status, sign): |
|||
r = requests.get( |
|||
"%(domain)s/dev/on_device_down/" % {'domain': SERVER_DOMAIN}, |
|||
params={ |
|||
'ip': ip, |
|||
'status': status, |
|||
'sign': sign |
|||
}) |
|||
if r.status_code == 200: |
|||
print(r.json()) |
|||
else: |
|||
print('Status:', r.status_code, r.text) |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
if len(sys.argv) < 3: |
|||
print('You forget parameters, example of usage:\n' |
|||
'$ python3 ./monitoring_agent.py 192.168.0.100 DOWN|UP|UNREACHABLE') |
|||
exit(0) |
|||
dev_ip = validate(IP_REGEXP, sys.argv[1]) |
|||
status = validate_status(sys.argv[2]) |
|||
|
|||
sign = calc_hash('_'.join((dev_ip, status, API_AUTH_SECRET))) |
|||
|
|||
send_request(dev_ip, status, sign) |
|||
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.11 on 2018-01-29 16:25 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('devapp', '0005_device_snmp_item_num'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='device', |
|||
options={'ordering': ['comment'], 'permissions': (('can_view_device', 'Can view device'),), 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'}, |
|||
), |
|||
migrations.AddField( |
|||
model_name='device', |
|||
name='is_noticeable', |
|||
field=models.BooleanField(default=False, verbose_name='Send notify when monitoring state changed'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='device', |
|||
name='status', |
|||
field=models.CharField(choices=[('und', 'Undefined'), ('up', 'Up'), ('unr', 'Unreachable'), ('dwn', 'Down')], default='und', max_length=3, verbose_name='Status'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='device', |
|||
name='snmp_item_num', |
|||
field=models.PositiveSmallIntegerField(blank=True, default=0, verbose_name='SNMP Number'), |
|||
), |
|||
] |
|||
@ -0,0 +1,57 @@ |
|||
from hashlib import sha256 |
|||
from django.views.generic.base import View |
|||
from django.http.response import HttpResponseForbidden |
|||
from django.conf import settings |
|||
from netaddr import IPNetwork, IPAddress |
|||
|
|||
|
|||
API_AUTH_SECRET = getattr(settings, 'API_AUTH_SECRET') |
|||
API_AUTH_SUBNET = getattr(settings, 'API_AUTH_SUBNET') |
|||
|
|||
|
|||
class HashAuthView(View): |
|||
|
|||
@staticmethod |
|||
def calc_hash(data): |
|||
if type(data) is str: |
|||
result_data = data.encode('utf-8') |
|||
else: |
|||
result_data = bytes(data) |
|||
return sha256(result_data).hexdigest() |
|||
|
|||
@staticmethod |
|||
def check_sign(get_list, sign): |
|||
hashed = '_'.join(get_list) |
|||
my_sign = HashAuthView.calc_hash(hashed) |
|||
return sign == my_sign |
|||
|
|||
def __init__(self, *args, **kwargs): |
|||
if API_AUTH_SECRET is None: |
|||
raise ImportError('You must specified API_AUTH_SECRET is settings') |
|||
else: |
|||
super(HashAuthView, self).__init__(*args, **kwargs) |
|||
|
|||
def dispatch(self, request, *args, **kwargs): |
|||
sign = request.GET.get('sign') |
|||
|
|||
# Transmittent get list without sign |
|||
get_values = request.GET.copy() |
|||
del get_values['sign'] |
|||
if HashAuthView.check_sign(list(get_values.values()) + [API_AUTH_SECRET], sign): |
|||
return super(HashAuthView, self).dispatch(request, *args, **kwargs) |
|||
else: |
|||
return HttpResponseForbidden('Access Denied') |
|||
|
|||
|
|||
class AllowedSubnetMixin(object): |
|||
|
|||
def dispatch(self, request, *args, **kwargs): |
|||
""" |
|||
Check if user ip in allowed subnet. |
|||
Return 403 denied otherwise. |
|||
""" |
|||
ip = IPAddress(request.META.get('REMOTE_ADDR')) |
|||
if ip in IPNetwork(API_AUTH_SUBNET): |
|||
return super(AllowedSubnetMixin, self).dispatch(request, *args, **kwargs) |
|||
else: |
|||
return HttpResponseForbidden('Access Denied') |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue