Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion module_com_bdd
Submodule module_com_bdd updated 0 files
2 changes: 1 addition & 1 deletion program_scanner
Submodule program_scanner updated 1 files
+35 −42 scanner.py
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ coveralls==1.1
django-phonenumber-field==1.1.0
django-bulk-update==1.1.10
stripe==1.37.0
django-simple-history
17 changes: 11 additions & 6 deletions vigilate_backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from django.utils.crypto import get_random_string
from django.conf import settings
from phonenumber_field.modelfields import PhoneNumberField

from simple_history.models import HistoricalRecords
# Create your models here.

def longer_password(sender, *args, **kwargs):
Expand Down Expand Up @@ -70,6 +70,7 @@ class User(AbstractBaseUser):
id_dealer = models.IntegerField(default=0)
plan = models.ForeignKey('Plans', default=None, null=True, on_delete=models.SET_DEFAULT)
plan_purchase_date = models.DateTimeField(auto_now=True)
history = HistoricalRecords()

is_superuser = models.BooleanField(default=False)
is_active = True
Expand Down Expand Up @@ -121,7 +122,8 @@ def set_password(self, password):
hsh = PyArgon2.Hash_pwd(password.encode(), salt.encode())
hsh = (salt.encode()+b"$"+binascii.hexlify(hsh)).decode("utf8")
self.password = hsh



def check_password(self, pwd):
"""Check if the given password match the real one
"""
Expand Down Expand Up @@ -166,7 +168,7 @@ class UserPrograms(models.Model):
web_score = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(10)], default=0)
web_enabled = models.BooleanField(default=True)
alert_type_default = models.BooleanField(default=True)

history = HistoricalRecords()

def alert_id(self):
return Alert.objects.filter(program=self.id).values_list('id', flat=True).first()
Expand All @@ -183,7 +185,8 @@ class Alert(models.Model):
program = models.ForeignKey('UserPrograms')
cve = models.ManyToManyField('vulnerability_manager.Cve')
view = models.BooleanField(default=False)

history = HistoricalRecords()

def max_cvss(self):
if self.cve.values_list("cvss_score", flat=True):
return max(self.cve.values_list("cvss_score", flat=True))
Expand Down Expand Up @@ -226,7 +229,8 @@ def get_random_token():
user = models.ForeignKey('User')
name = models.CharField(max_length=100)
disabled = models.BooleanField(default=False)

history = HistoricalRecords()

def generate_token(self):
self.token = get_random_token()

Expand All @@ -243,7 +247,7 @@ def get_random_token():
token = models.CharField(max_length=50, default=get_random_token, primary_key=True, unique=True)
user = models.ForeignKey('User', null=True, default=None)
date = models.DateTimeField(auto_now=True)

history = HistoricalRecords()
def is_valid(self):
delta = now() - self.date

Expand All @@ -252,3 +256,4 @@ def is_valid(self):
return True
class Meta:
verbose_name_plural = "Sessions"

22 changes: 2 additions & 20 deletions vigilate_backend/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def create(self, validated_data):
def validate(self, data):
if not hasattr(self.instance, "id"):
return data

prev_state = models.User.objects.get(id=self.instance.id)
if 'default_alert_type' in data and data['default_alert_type'] == models.User.SMS and\
(('phone' in data and not data['phone']) or (not 'phone' in data and not prev_state.phone)):
Expand Down Expand Up @@ -59,6 +59,7 @@ class Meta:
def create(self, validated_data):
"""Create an user program
"""
validated_data['program_version'] = validated_data['program_version'][0]
return models.UserPrograms.objects.create(**validated_data)

def validate(self, data):
Expand All @@ -67,25 +68,6 @@ def validate(self, data):
raise serializers.ValidationError({'sms_enabled': ['Cannot enable sms alert for an user without a phone number registered']})
return data

def update(self, instance, validated_data):
"""Update an user program
"""
instance.id = validated_data.get('id', instance.id)
instance.program_name = validated_data.get('program_name', instance.program_name)
instance.program_version = validated_data.get('program_version', instance.program_version)
instance.minimum_score = validated_data.get('minimum_score', instance.minimum_score)
instance.user = validated_data.get('user', instance.user)
instance.poste = validated_data.get('poste', instance.poste)
instance.sms_score = validated_data.get('sms_score', instance.sms_score)
instance.email_score = validated_data.get('email_score', instance.email_score)
instance.web_score = validated_data.get('web_score', instance.web_score)
instance.sms_enabled = validated_data.get('sms_enabled', instance.sms_enabled)
instance.email_enabled = validated_data.get('email_enabled', instance.email_enabled)
instance.web_enabled = validated_data.get('web_enabled', instance.web_enabled)
instance.alert_type_default = validated_data.get('alert_type_default', instance.alert_type_default)
instance.save()
return instance

class AlertSerializer(serializers.ModelSerializer):
"""Serialisation of user alerts
"""
Expand Down
2 changes: 2 additions & 0 deletions vigilate_backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'vigilate_backend',
'vulnerability_manager',
'django_nose',
'simple_history',
)

MIDDLEWARE_CLASSES = (
Expand All @@ -57,6 +58,7 @@
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'middleware.vigilateMiddleware.VigilateMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
)

ROOT_URLCONF = 'vigilate_backend.urls'
Expand Down
2 changes: 0 additions & 2 deletions vigilate_backend/tests/test_Alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ def test_alert_when_prog_vuln_update(self):
json.dumps(test_Alert_data.prog_vuln),
content_type="application/json")

print(resp.content)

self.assertEqual(resp.status_code, 200)
resp = self.client.get(basic_data.api_routes['alerts'])
data = json.loads(resp.content.decode("utf8"))
Expand Down
10 changes: 5 additions & 5 deletions vigilate_backend/tests/test_Alert_data.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from dateutil.parser import parse as parse_date

prog_not_vuln = {"program_name" : "firefox", "program_version" : "1337", "minimum_score": 0,"poste": "changed"}
prog_vuln = {"program_name" : "bzip2", "program_version" : "1.0.6", "minimum_score": 1,"poste": "changed"}
prog_vuln2 = {"program_name" : "glibc", "program_version" : "2.23", "minimum_score": 1,"poste": "changed"}
prog_not_vuln = {"program_name" : "firefox", "program_version" : ["1337"], "minimum_score": 0,"poste": "changed"}
prog_vuln = {"program_name" : "bzip2", "program_version" : ["1.0.6"], "minimum_score": 1,"poste": "changed"}
prog_vuln2 = {"program_name" : "glibc", "program_version" : ["2.23"], "minimum_score": 1,"poste": "changed"}
prog_vuln_multi = [prog_vuln, prog_vuln2]
prog_vuln_sms = {"program_name" : "bzip2", "program_version" : "1.0.6", "minimum_score": 1,"poste": "changed", "alert_type_default": False, "sms_enabled": True, "sms_score": 0}
prog_vuln_sms = {"program_name" : "bzip2", "program_version" : ["1.0.6"], "minimum_score": 1,"poste": "changed", "alert_type_default": False, "sms_enabled": True, "sms_score": 0}

prog_vuln_before_update = {"program_name" : "bzip2", "program_version" : "1.0.5", "minimum_score": 0,"poste": "changed"}
prog_vuln_before_update = {"program_name" : "bzip2", "program_version" : ["1.0.5"], "minimum_score": 0,"poste": "changed"}

proglist_vuln = {"programs_list": [prog_vuln], "poste": "changed"}
proglist_vuln_multi = {"programs_list": prog_vuln_multi, "poste": "changed"}
Expand Down
4 changes: 2 additions & 2 deletions vigilate_backend/tests/test_ScannerToken_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
prog_list_to_submit = {"programs_list" :
[
{"program_name" : "mozilla firefox", "program_version" : "31.0"},
{"program_name" : "blabla", "program_version" : "2.0.1"}
{"program_name" : "mozilla firefox", "program_version" : ["31.0"]},
{"program_name" : "blabla", "program_version" : ["2.0.1"]}
],
"poste" : "changed"}
scanner = {"name": "Test station"}
Expand Down
7 changes: 4 additions & 3 deletions vigilate_backend/tests/test_UserPrograms.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_submit_one_program(self):
user_progs = models.UserPrograms.objects.filter(user=self.new_user["id"])

prog_saved = {"program_name" : user_progs[0].program_name, "program_version" : user_progs[0].program_version}
prog_sent = {"program_name" : prog["program_name"], "program_version" : prog["program_version"]}
prog_sent = {"program_name" : prog["program_name"], "program_version" : prog["program_version"][0]}

self.assertEqual(prog_sent, prog_saved)

Expand All @@ -54,12 +54,12 @@ def test_submit_one_program_json_encoded(self):

resp = self.client.post(basic_data.api_routes['programs'], json.dumps(prog),
content_type="application/json")

self.assertEqual(resp.status_code, 200)
user_progs = models.UserPrograms.objects.filter(user=self.new_user["id"])

prog_saved = {"program_name" : user_progs[0].program_name, "program_version" : user_progs[0].program_version}
prog_sent = {"program_name" : prog["program_name"], "program_version" : prog["program_version"]}
prog_sent = {"program_name" : prog["program_name"], "program_version" : prog["program_version"][0]}

self.assertEqual(prog_sent, prog_saved)

Expand All @@ -76,4 +76,5 @@ def test_submit_multiples_programs(self):
database_programs_json.append(elem)

for sent in prog_list['programs_list']:
sent['program_version'] = sent['program_version'][0]
self.assertTrue(sent in database_programs_json)
6 changes: 3 additions & 3 deletions vigilate_backend/tests/test_UserPrograms_data.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
prog_to_submit = [{"program_name" : "Google Chrome", "program_version" : "51.0", "minimum_score": 0,"poste": "changed"}]
prog_to_submit = [{"program_name" : "Google Chrome", "program_version" : ["51.0"], "minimum_score": 0,"poste": "changed"}]
prog_list_to_submit = [{"programs_list" :
[
{"program_name" : "mozilla firefox", "program_version" : "31.0"},
{"program_name" : "blabla", "program_version" : "2.0.1"}
{"program_name" : "mozilla firefox", "program_version" : ["31.0"]},
{"program_name" : "blabla", "program_version" : ["2.0.1"]}
],
"poste" : "changed"}]
scanner = {"name": "Test station"}
35 changes: 33 additions & 2 deletions vigilate_backend/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import json
import base64
from vigilate_backend.models import Station, User, Plans
from vigilate_backend.models import Station, User, Plans, UserPrograms
from django.utils import timezone
from vigilate_backend.models import UserPrograms
from vigilate_backend import alerts
from vulnerability_manager import cpe_updater

def get_query(request):
"""Parse a query
"""
if request.method == "POST":
if request.method == "POST" or request.method == "PATCH":
if "application/json" in request.content_type:
return request.data
query = list(request.data)[0]
Expand Down Expand Up @@ -130,3 +133,31 @@ def check_expired_plan(user):
user.plan = Plans.objects.filter(default=True).first()
user.save()
update_contrat(user)

def add_progs(elem, versions, user, station, extra_field, up_to_date):
for version in versions:
(cpe, up_to_date) = cpe_updater.get_cpe_from_name_version(elem['program_name'], version, up_to_date)
new_prog = UserPrograms(user=user, minimum_score=1, poste=station,
program_name=elem['program_name'], program_version=version, cpe=cpe)
if 'minimum_score' in elem:
new_prog.minimum_score = int(elem['minimum_score'])
for f in extra_field:
setattr(new_prog, f, int(extra_field[f]))

new_prog.save()
alerts.check_prog(new_prog, user)

def maj_progs(progs, elem, versions, user, up_to_date):
for (prog, version) in zip(progs, versions):
prog_changed = False
if prog.program_version != version:
prog_changed = True
prog.program_version = version
(cpe, up_to_date) = cpe_updater.get_cpe_from_name_version(elem['program_name'], version, up_to_date)
prog.cpe = cpe
if 'minimum_score' in elem and prog.minimum_score != int(elem['minimum_score']):
prog_changed = True
prog.minimum_score = int(elem['minimum_score'])
if prog_changed:
prog.save()
alerts.check_prog(prog, user)
88 changes: 41 additions & 47 deletions vigilate_backend/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.exceptions import AuthenticationFailed
from pkg_resources import parse_version
from vigilate_backend.utils import get_query, parse_cpe, get_token, get_scanner_cred, nb_station_over_quota, update_contrat
from vigilate_backend.utils import get_query, parse_cpe, get_token, get_scanner_cred, nb_station_over_quota, update_contrat, add_progs, maj_progs
from vigilate_backend.models import User, UserPrograms, Alert, Station, Session, Plans
from vigilate_backend.serializers import UserSerializer, UserProgramsSerializer, AlertSerializer, AlertSerializerDetail, StationSerializer, SessionSerializer, PlansSerializer
from vigilate_backend import alerts
Expand Down Expand Up @@ -171,9 +171,6 @@ def create(self, request):
extra_field[k] = query[k]

query['programs_list'] = [elem]
if UserPrograms.objects.filter(user=request.user.id, program_name=elem['program_name'], poste=station).exists():
ret = {"program_name": ["A program with this name already exists for station %s" % (station.name)]}
return Response(ret, status=status.HTTP_400_BAD_REQUEST)

for elem in query['programs_list']:
if not all(x in elem for x in ['program_version', 'program_name']):
Expand All @@ -184,60 +181,57 @@ def create(self, request):
up_to_date = True

for elem in query['programs_list']:
prog = UserPrograms.objects.filter(user=request.user.id, program_name=elem['program_name'], poste=station)
progs = UserPrograms.objects.filter(user=request.user.id, program_name=elem['program_name'], poste=station)

# if prog, user is already monitoring the given program, update is needed
if prog:
if progs:

prog = prog[0]
prog_changed = False
if prog.program_version != elem['program_version']:
prog_changed = True
prog.program_version = elem['program_version']
(cpe, up_to_date) = cpe_updater.get_cpe_from_name_version(elem['program_name'], elem['program_version'], up_to_date)
prog.cpe = cpe
if 'minimum_score' in elem and prog.minimum_score != int(elem['minimum_score']):
prog_changed = True
prog.minimum_score = int(elem['minimum_score'])
if prog_changed:
prog.save()
alerts.check_prog(prog, request.user)
if len(progs) == len(elem['program_version']):
maj_progs(progs, elem, elem['program_version'], request.user, up_to_date)
elif len(progs) > len(elem['program_version']):
# maj as much progs as tehy are in the data from the scanner
maj_progs(progs[:len(elem['program_version'])], elem, elem['program_version'], request.user, up_to_date)
# delete other progs with same name
for prog in progs[len(elem['program_version']):]:
prog.delete()
else:
# maj as much progs as tehy are in db
maj_progs(progs, elem, elem['program_version'][:len(progs)], request.user, up_to_date)
# create the other ones
add_progs(elem, elem['program_version'][len(progs):], request.user, station, extra_field, up_to_date)
else:
#else: add a new program
#else: add new programs
add_progs(elem, elem['program_version'], request.user, station, extra_field, up_to_date)

(cpe, up_to_date) = cpe_updater.get_cpe_from_name_version(elem['program_name'], elem['program_version'], up_to_date)

new_prog = UserPrograms(user=request.user, minimum_score=1, poste=station,
program_name=elem['program_name'], program_version=elem['program_version'], cpe=cpe)
if 'minimum_score' in elem:
new_prog.minimum_score = int(elem['minimum_score'])
for f in extra_field:
setattr(new_prog, f, int(extra_field[f]))

new_prog.save()
alerts.check_prog(new_prog, request.user)

if only_one_program:
obj = UserPrograms.objects.get(user=request.user.id, program_name=elem['program_name'], poste=station)
if only_one_program: # this sould happen only when the request came from the frontend
obj = UserPrograms.objects.get(user=request.user.id, program_name=elem['program_name'], poste=station, program_version=elem['program_version'][0])
serializer = self.get_serializer(obj)
return Response(serializer.data, status=status.HTTP_200_OK)

return Response(status=status.HTTP_200_OK)


def perform_update(self, serializer):
orig = UserPrograms.objects.get(id=serializer.instance.id)
def update(self, request, pk=None, partial=None):
prog = UserPrograms.objects.get(id=pk)
check = False
if orig.program_version != serializer.validated_data['program_version'] or \
orig.program_name != serializer.validated_data['program_name']:
check = True
instance = serializer.save()
(cpe, _) = cpe_updater.get_cpe_from_name_version(instance.program_name, instance.program_version, True)
instance.cpe = cpe
instance.save(update_fields=["cpe"])
if check:
alerts.check_prog(instance, self.request.user)

query = get_query(request)
if query:
if prog.program_version != query['program_version'][0] or \
prog.program_name != query['program_name']:
check = True
prog.program_version = query['program_version'][0]
prog.program_name = query['program_name']
for k in ['sms_score', 'sms_enabled', 'email_score', 'email_enabled',
'web_score', 'web_enabled', 'alert_type_default']:
if k in query:
setattr(prog, k, query[k])
(cpe, _) = cpe_updater.get_cpe_from_name_version(prog.program_name, prog.program_version, True)
prog.cpe = cpe
prog.save()
if check:
alerts.check_prog(prog, self.request.user)
serializer = self.get_serializer(prog)
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(status=status.HTTP_200_OK)

class AlertViewSet(viewsets.ModelViewSet):
"""View for alerts
Expand Down