Skip to content
This repository has been archived by the owner on Sep 16, 2022. It is now read-only.

Remove local firewall #817

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion backend/device_registry/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class FirewallStateAdmin(admin.ModelAdmin):
list_display = [
'device',
'scan_date',
'policy'
]

ordering = ('scan_date',)
Expand Down
8 changes: 4 additions & 4 deletions backend/device_registry/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ def get(self, request, *args, **kwargs):
policy_string = firewallstate_object.global_policy.policy_string
ports_field_name = firewallstate_object.global_policy.ports_field_name
else: # User's per-device security settings.
block_networks = portscan_object.block_networks.copy()
block_ports = portscan_object.block_ports
policy_string = firewallstate_object.policy_string
ports_field_name = firewallstate_object.ports_field_name
block_networks = []
block_ports = []
policy_string = 'allow'
ports_field_name = 'block_ports'
block_networks.extend(settings.SPAM_NETWORKS)
return Response({
'policy': policy_string, ports_field_name: block_ports, 'block_networks': block_networks,
Expand Down
26 changes: 0 additions & 26 deletions backend/device_registry/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,6 @@ class Meta:
}


class PortsForm(forms.Form):
policy = forms.ChoiceField(choices=FirewallState.POLICY_CHOICES,
widget=forms.Select(attrs={'class': 'wott-form-control custom-select'}))
open_ports = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple(attrs={'class': 'list-unstyled'}))
is_ports_form = forms.CharField(widget=forms.HiddenInput, initial='true')

def __init__(self, *args, **kwargs):
ports_choices = kwargs.pop('ports_choices')
super().__init__(*args, **kwargs)
self.fields['open_ports'].choices = ports_choices


class ConnectionsForm(forms.Form):
open_connections = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple(attrs={'class': 'list-unstyled'}))
is_connections_form = forms.CharField(widget=forms.HiddenInput, initial='true')

def __init__(self, *args, **kwargs):
open_connections_choices = kwargs.pop('open_connections_choices')
super().__init__(*args, **kwargs)
self.fields['open_connections'].choices = open_connections_choices


class FirewallStateGlobalPolicyForm(forms.ModelForm):
class Meta:
model = FirewallState
Expand Down
8 changes: 2 additions & 6 deletions backend/device_registry/migrations/0084_ra_remove_fields.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import device_registry.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
from django.db.models import Case, CharField, Value, When
from django.db import migrations


def update_default_credentials(apps, schema_editor):
Expand Down Expand Up @@ -43,6 +40,5 @@ class Migration(migrations.Migration):
migrations.RemoveField(
model_name='recommendedaction',
name='status',
),
migrations.RunPython(update_default_credentials)
)
]
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ class Migration(migrations.Migration):
model_name='debpackage',
name='name',
field=models.CharField(db_index=True, max_length=128),
),
migrations.RunPython(update_default_credentials)
)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 2.2.11 on 2020-03-25 13:55

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('device_registry', '0092_auto_20200403_1153'),
]

operations = [
migrations.RemoveField(
model_name='firewallstate',
name='policy',
),
]
113 changes: 2 additions & 111 deletions backend/device_registry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ def zero_if_none(x):

return self.calculate_trust_score(
app_armor_enabled=zero_if_none(self.deviceinfo.app_armor_enabled),
firewall_enabled=self.firewallstate.policy == FirewallState.POLICY_ENABLED_BLOCK,
firewall_enabled=bool(self.firewallstate.global_policy
and self.firewallstate.global_policy.policy == GlobalPolicy.POLICY_BLOCK),
selinux_enabled=selinux.get('enabled', False),
selinux_enforcing=(selinux.get('mode') == 'enforcing'),
failed_logins=failed_logins,
Expand Down Expand Up @@ -698,123 +699,13 @@ def get_score(self):
score -= 0.3
return max(round(score, 1), 0)

def ports_form_data(self):
"""
Build 3 lists:
1) list of choices for the ports form:
[(0, ''), (1, '')]
2) list of initial values for the ports form:
[0, 1]
3) list of choices for saving to the block list:
[['::ffff:192.168.1.178', 22, 'tcp', True], ['192.168.1.178', 33, 'udp', False]]
and 1 dict:
1) dictionary of choices' extra data:
{0: ('192.168.1.178', 33, 'UDP', 4, 'html for process info popover(optional)'),
1: ('::ffff:192.168.1.178', 22, 'TCP', 6, None)}
"""
choices_data = []
initial_data = []
ports_data = []
choices_extra_data = {}

port_record_index = 0
# 1st - take ports from the block list.
for port_record in self.block_ports:
choices_data.append((port_record_index, ''))
choices_extra_data[port_record_index] = (port_record[0], port_record[2], port_record[1].upper(),
6 if port_record[3] else 4, None)
ports_data.append(port_record)
initial_data.append(port_record_index)
port_record_index += 1
# 2nd - take ports from the open ports list (only the ones missing in the block list).
for port_record in self.scan_info:
if [port_record['host'], port_record['proto'], port_record['port'], port_record['ip_version'] == 6] \
not in self.block_ports:
choices_data.append((port_record_index, ''))
choices_extra_data[port_record_index] = (port_record['host'], port_record['port'],
port_record['proto'].upper(), port_record['ip_version'],
self.get_process_info_html(port_record))
ports_data.append([port_record['host'], port_record['proto'], port_record['port'],
port_record['ip_version'] == 6])
port_record_index += 1
return choices_data, initial_data, ports_data, choices_extra_data

def connections_form_data(self):
"""
Build 3 lists:
1) list of choices for the open connections form
(gonna be split in a template by '/' separator)::
[[0, '192.168.1.20/4567/192.168.1.178/80/4/TCP/open/3425']]
2) list of initial values for the open connections form:
[0]
3) list of choices for saving to the block list:
[['192.168.1.20', False], ['::ffff:192.168.1.25', True]]
"""
initial_data = []
choices_data = []
connections_data = []
connection_record_index = 0
unique_addresses = set()

# 1st - take addresses from the block list.
for connection_record in self.block_networks:
if tuple(connection_record) not in unique_addresses:
unique_addresses.add(tuple(connection_record))
choices_data.append((connection_record_index, '%s////%d///' % (connection_record[0],
6 if connection_record[1] else 4)))
connections_data.append(connection_record)
initial_data.append(connection_record_index)
connection_record_index += 1

# 2nd - take addresses from the open connections list (only the ones missing in the block list).
for connection_record in self.netstat:
if connection_record['remote_address'] and (connection_record['remote_address'][0],
connection_record['ip_version'] == 6) not in unique_addresses:
unique_addresses.add((connection_record['remote_address'][0], connection_record['ip_version'] == 6))
choices_data.append((
connection_record_index, '%s/%s/%s/%s/%d/%s/%s/%s' %
(connection_record['remote_address'][0], connection_record['remote_address'][1],
connection_record['local_address'][0] if connection_record['local_address'] else '',
connection_record['local_address'][1] if connection_record['local_address'] else '',
connection_record['ip_version'], connection_record['type'].upper(),
connection_record['status'], connection_record['pid'])))
connections_data.append([connection_record['remote_address'][0],
connection_record['ip_version'] == 6])
connection_record_index += 1
return choices_data, initial_data, connections_data


class FirewallState(models.Model):
POLICY_ENABLED_ALLOW = 1
POLICY_ENABLED_BLOCK = 2
POLICY_CHOICES = (
(POLICY_ENABLED_ALLOW, 'Allow by default'),
(POLICY_ENABLED_BLOCK, 'Block by default')
)
device = models.OneToOneField(Device, on_delete=models.CASCADE)
scan_date = models.DateTimeField(null=True, auto_now_add=True)
rules = JSONField(blank=True, default=dict)
policy = models.PositiveSmallIntegerField(choices=POLICY_CHOICES, default=POLICY_ENABLED_ALLOW)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the POLICY_CHOICES declaration since it's not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

global_policy = models.ForeignKey('GlobalPolicy', on_delete=models.SET_NULL, blank=True, null=True)

@property
def policy_string(self):
if self.policy == self.POLICY_ENABLED_ALLOW:
return 'allow'
elif self.policy == self.POLICY_ENABLED_BLOCK:
return 'block'
else:
raise NotImplementedError

@property
def ports_field_name(self):
if self.policy == self.POLICY_ENABLED_ALLOW:
return 'block_ports'
elif self.policy == self.POLICY_ENABLED_BLOCK:
return 'allow_ports'
else:
raise NotImplementedError

@property
def beautified_rules(self):
return yaml.dump(self.rules) if self.rules else "none"
Expand Down
23 changes: 9 additions & 14 deletions backend/device_registry/recommended_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from typing import NamedTuple, List
from urllib.parse import urljoin

import redis
from django.conf import settings
from django.db.models import Q, QuerySet, Max, F
from django.urls import reverse
Expand Down Expand Up @@ -468,25 +467,21 @@ def get_class(meta, id):

# Firewall disabled action.
class FirewallDisabledAction(SimpleAction, metaclass=ActionMeta):
_severity = Severity.MED

@classmethod
def _affected_devices(cls, qs):
from .models import FirewallState, GlobalPolicy
return qs.exclude(
(Q(firewallstate__global_policy=None) & Q(firewallstate__policy=FirewallState.POLICY_ENABLED_BLOCK)) |
Q(firewallstate__global_policy__policy=GlobalPolicy.POLICY_BLOCK))
from .models import GlobalPolicy
return qs.exclude(firewallstate__global_policy__policy=GlobalPolicy.POLICY_BLOCK)

@classmethod
def _is_affected(cls, device) -> bool:
from .models import FirewallState, GlobalPolicy
from .models import GlobalPolicy
firewallstate = getattr(device, 'firewallstate', None)
return firewallstate is not None and \
(firewallstate.policy != FirewallState.POLICY_ENABLED_BLOCK
if firewallstate.global_policy is None
else firewallstate.global_policy.policy != GlobalPolicy.POLICY_BLOCK)

@classmethod
def severity(cls, param=None):
return Severity.MED
if firewallstate and firewallstate.global_policy and firewallstate.global_policy.policy \
== GlobalPolicy.POLICY_BLOCK:
return False
return True


# OS reboot required action.
Expand Down