Commit 9fb5f44b by Bach Dániel

Merge branch 'feature-fw-api' into 'master'

Feature fw api 

See merge request !297
parents 59cb3f57 4a0abb1e
......@@ -564,3 +564,6 @@ MAX_NODE_RAM = get_env_variable("MAX_NODE_RAM", 1024)
CLIENT_DOWNLOAD_URL = get_env_variable('CLIENT_DOWNLOAD_URL', 'http://circlecloud.org/client/download/')
ADMIN_ENABLED = False
BLACKLIST_PASSWORD = get_env_variable("BLACKLIST_PASSWORD", "")
BLACKLIST_HOOK_URL = get_env_variable("BLACKLIST_HOOK_URL", "")
......@@ -27,21 +27,16 @@ from django.shortcuts import redirect
from circle.settings.base import get_env_variable
from dashboard.views import circle_login, HelpView
from dashboard.forms import CirclePasswordResetForm, CircleSetPasswordForm
from firewall.views import add_blacklist_item
admin.autodiscover()
urlpatterns = patterns(
'',
# url(r'^$', TemplateView.as_view(template_name='base.html')),
# Examples:
# url(r'^$', 'circle.views.home', name='home'),
# url(r'^circle/', include('circle.foo.urls')),
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^$', lambda x: redirect(reverse("dashboard.index"))),
url(r'^network/', include('network.urls')),
url(r'^blacklist-add/', add_blacklist_item),
url(r'^dashboard/', include('dashboard.urls')),
# django/contrib/auth/urls.py (care when new version)
......
......@@ -132,7 +132,8 @@ class RecordAdmin(admin.ModelAdmin):
class BlacklistItemAdmin(admin.ModelAdmin):
list_display = ('ipv4', 'type', 'reason', 'created_at', 'modified_at')
list_display = ('ipv4', 'whitelisted', 'reason', 'expires_at',
'created_at', 'modified_at')
class SwitchPortAdmin(admin.ModelAdmin):
......
......@@ -19,14 +19,12 @@ import re
import logging
from collections import OrderedDict
from netaddr import IPAddress, AddrFormatError
from datetime import timedelta
from itertools import product
from .models import (Host, Rule, Vlan, Domain, Record, BlacklistItem,
SwitchPort)
from .iptables import IptRule, IptChain
import django.conf
from django.db.models import Q
from django.template import loader, Context
from django.utils import timezone
......@@ -161,10 +159,9 @@ class BuildFirewall:
def ipset():
week = timezone.now() - timedelta(days=2)
filter_ban = (Q(type='tempban', modified_at__gte=week) |
Q(type='permban'))
return BlacklistItem.objects.filter(filter_ban).values('ipv4', 'reason')
now = timezone.now()
return BlacklistItem.objects.filter(whitelisted=False).exclude(
expires_at__lt=now).values('ipv4', 'reason')
def ipv6_to_octal(ipv6):
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('firewall', '0002_auto_20150115_0021'),
]
operations = [
migrations.RemoveField(
model_name='blacklistitem',
name='type',
),
migrations.AddField(
model_name='blacklistitem',
name='expires_at',
field=models.DateTimeField(default=None, null=True, verbose_name='expires at', blank=True),
preserve_default=True,
),
migrations.AddField(
model_name='blacklistitem',
name='whitelisted',
field=models.BooleanField(default=False, verbose_name='whitelisted'),
preserve_default=True,
),
migrations.AlterField(
model_name='blacklistitem',
name='ipv4',
field=models.GenericIPAddressField(protocol=b'ipv4', unique=True, verbose_name=b'IPv4 address'),
preserve_default=True,
),
migrations.AlterField(
model_name='blacklistitem',
name='reason',
field=models.TextField(null=True, verbose_name='reason', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='blacklistitem',
name='snort_message',
field=models.TextField(null=True, verbose_name='short message', blank=True),
preserve_default=True,
),
]
......@@ -1109,24 +1109,23 @@ class EthernetDevice(models.Model):
class BlacklistItem(models.Model):
CHOICES_type = (('permban', 'permanent ban'), ('tempban', 'temporary ban'),
('whitelist', 'whitelist'), ('tempwhite', 'tempwhite'))
ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
host = models.ForeignKey('Host', blank=True, null=True,
verbose_name=_('host'))
reason = models.TextField(blank=True, verbose_name=_('reason'))
snort_message = models.TextField(blank=True,
verbose_name=_('short message'))
type = models.CharField(
max_length=10,
choices=CHOICES_type,
default='tempban',
verbose_name=_('type')
)
ipv4 = models.GenericIPAddressField(
protocol='ipv4', unique=True, verbose_name=("IPv4 address"))
host = models.ForeignKey(
'Host', blank=True, null=True, verbose_name=_('host'))
reason = models.TextField(
blank=True, null=True, verbose_name=_('reason'))
snort_message = models.TextField(
blank=True, null=True, verbose_name=_('short message'))
whitelisted = models.BooleanField(
default=False, verbose_name=_("whitelisted"))
created_at = models.DateTimeField(auto_now_add=True,
verbose_name=_('created_at'))
modified_at = models.DateTimeField(auto_now=True,
verbose_name=_('modified_at'))
expires_at = models.DateTimeField(blank=True, null=True, default=None,
verbose_name=_('expires at'))
def save(self, *args, **kwargs):
self.full_clean()
......
......@@ -102,6 +102,7 @@ def reloadtask(type='Host', timeout=15):
'Rule': ['firewall'],
'SwitchPort': ['firewall_vlan'],
'EthernetDevice': ['firewall_vlan'],
'BlacklistItem': ['blacklist'],
}[type]
logger.info("Reload %s on next periodic iteration applying change to %s.",
", ".join(reload), type)
......
......@@ -15,69 +15,97 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import base64
import datetime
import json
from __future__ import absolute_import, unicode_literals
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from datetime import timedelta
from json import dumps
import logging
from netaddr import AddrFormatError, IPAddress
from requests import post
from requests.exceptions import RequestException
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.utils.timezone import utc
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from .tasks.local_tasks import reloadtask
from .models import BlacklistItem, Host
from django.conf import settings
def reload_firewall(request):
if request.user.is_authenticated():
if request.user.is_superuser:
html = (_("Dear %s, you've signed in as administrator!<br />"
"Reloading in 10 seconds...") % request.user.username)
reloadtask.delay()
reloadtask.delay('Vlan')
else:
html = (_("Dear %s, you've signed in!") % request.user.username)
logger = logging.getLogger(__name__)
def send_request(obj):
data = {"ip": obj.ipv4,
"msg": obj.snort_message,
"reason": obj.reason,
"expires_at": str(obj.expires_at).split('.')[0],
"object_kind": "ban"}
if obj.host:
data.update({"hostname": obj.host.hostname,
"username": obj.host.owner.username,
"fullname": obj.host.owner.get_full_name()})
try:
r = post(settings.BLACKLIST_HOOK_URL, data=dumps(data, indent=2),
timeout=3)
r.raise_for_status()
except RequestException as e:
logger.warning("Error in HTTP POST: %s. url: %s params: %s",
str(e), settings.BLACKLIST_HOOK_URL, data)
else:
html = _("Dear anonymous, you've not signed in yet!")
return HttpResponse(html)
logger.info("Successful HTTP POST. url: %s params: %s",
settings.BLACKLIST_HOOK_URL, data)
@csrf_exempt
@require_POST
def firewall_api(request):
def add_blacklist_item(request):
password = request.POST.get('password')
if (not settings.BLACKLIST_PASSWORD or
password != settings.BLACKLIST_PASSWORD):
logger.warning("Tried invalid password. Password: %s IP: %s",
password, request.META["REMOTE_ADDR"])
raise PermissionDenied()
try:
data = json.loads(base64.b64decode(request.POST["data"]))
command = request.POST["command"]
if data["password"] != "bdmegintelrontottaanetet":
raise Exception(_("Wrong password."))
if command == "blacklist":
obj, created = BlacklistItem.objects.get_or_create(ipv4=data["ip"])
obj.reason = data["reason"]
obj.snort_message = data["snort_message"]
address = request.POST.get('address')
address_object = IPAddress(address, version=4)
except (AddrFormatError, TypeError) as e:
logger.warning("Invalid IP address: %s (%s)", address, str(e))
return HttpResponse(_("Invalid IP address."))
obj, created = BlacklistItem.objects.get_or_create(ipv4=address)
if created:
try:
obj.host = Host.objects.get(ipv4=data["ip"])
except (Host.DoesNotExist, ValidationError,
IntegrityError, AttributeError):
db_format = '.'.join("%03d" % x for x in address_object.words)
obj.host = Host.objects.get(ipv4=db_format)
except Host.DoesNotExist:
pass
modified = obj.modified_at + datetime.timedelta(minutes=1)
now = datetime.dateime.utcnow().replace(tzinfo=utc)
if obj.type == 'tempwhite' and modified < now:
obj.type = 'tempban'
if obj.type != 'whitelist':
now = timezone.now()
can_update = (
(obj.whitelisted and obj.expires_at and now > obj.expires_at) or
not obj.whitelisted)
is_new = created or (obj.expires_at and now > obj.expires_at)
if created or can_update:
obj.reason = request.POST.get('reason')
obj.snort_message = request.POST.get('snort_message')
obj.whitelisted = False
obj.expires_at = now + timedelta(weeks=1)
obj.full_clean()
obj.save()
return HttpResponse(unicode(_("OK")))
else:
raise Exception(_("Unknown command."))
except (ValidationError, IntegrityError, AttributeError, Exception) as e:
return HttpResponse(_("Something went wrong!\n%s\n") % e)
except:
return HttpResponse(_("Something went wrong!\n"))
if created:
logger.info("Successfully created blacklist item %s.", address)
elif can_update:
logger.info("Successfully modified blacklist item %s.", address)
if is_new and settings.BLACKLIST_HOOK_URL:
send_request(obj)
return HttpResponse(unicode(_("OK")))
......@@ -54,8 +54,10 @@ class BlacklistItemForm(ModelForm):
'',
'ipv4',
'host',
'expires_at',
'whitelisted',
'reason',
'type',
'snort_message',
)
),
FormActions(
......
......@@ -20,7 +20,8 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.html import format_html
from django_tables2 import Table, A
from django_tables2.columns import LinkColumn, TemplateColumn, Column
from django_tables2.columns import (LinkColumn, TemplateColumn, Column,
BooleanColumn)
from firewall.models import Host, Vlan, Domain, Group, Record, Rule, SwitchPort
......@@ -41,12 +42,14 @@ class MACColumn(Column):
class BlacklistItemTable(Table):
ipv4 = LinkColumn('network.blacklist', args=[A('pk')])
whitelisted = BooleanColumn()
class Meta:
model = Domain
attrs = {'class': 'table table-striped table-condensed'}
fields = ('ipv4', 'host', 'reason', 'type')
order_by = ('ipv4', )
fields = ('ipv4', 'host', 'reason', 'whitelisted', 'expires_at',
'created_at')
order_by = ('-expires_at', )
class DomainTable(Table):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment