Skip to content

Commit

Permalink
Version 2.0.3 (#76)
Browse files Browse the repository at this point in the history
* Updates to version 1.50.6

* Updated Django 3.2 version 2.0.3
  • Loading branch information
sei-vsarvepalli authored Dec 16, 2022
1 parent 11a590c commit d0dbbc9
Show file tree
Hide file tree
Showing 51 changed files with 1,894 additions and 1,650 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# VINCE Changelog


## Version 2.0.3: 2022-12-14

* Major upgrade to Django 3.2 LTS target end byt 2024. Fixes related to Django upgrade in all libraries.
* Aded new QuerySet Paging library for performance extend chain with chainqs for QuerySet
* Asynchronous calls for most vinny/views via JSON through asyncLoad class
* Provide API Views 404 with JSON generic error
* Allow Session or API Token authentication to support API access from browser
* Provide better HTML text on access/permission violations by User.
* Fixes to CVE management API with CVE services 2.1 and CVEJSON5 support
* CSAF enchancements including TLP setup. Pending Customer engagement details publishing.
* Fix number of logging to include relevant data as part of log message

## Version 1.50.6: 2022-11-04

* Allow Vendor Association when Ticket is associated with a Case
Expand Down
50 changes: 49 additions & 1 deletion bigvince/settings_.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
ROOT_DIR = environ.Path(__file__) - 3

# any change that requires database migrations is a minor release
VERSION = "1.50.6"
VERSION = "2.0.3"

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
Expand Down Expand Up @@ -756,3 +756,51 @@ def get_secret(secret_arn):

#allowed options: "prod", "test", "dev"
CVE_SERVICES_API = os.environ.get("CVE_SERVICES_API", "test")

#Django 3 and 4 upgrade
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

#TLP related statements Note TLP2.0 says WHITE is replaced by CLEAR BUT CSAF2.0 is in TLP1.0
#https://github.com/oasis-tcs/csaf/issues/591
CSAF_DISTRIBUTION_OPTIONS = {
"RED": {
"distribution": {
"text": "For the eyes and ears of individual recipients only, no further disclosure.",
"tlp": {
"label": "RED",
"url": "https://www.first.org/tlp/"
}
}
},
"AMBER": {
"distribution": {
"text": "Limited disclosure, recipients can only spread this on a need-to-know basis within their organization and its clients.",
"tlp": {
"label": "AMBER",
"url": "https://www.first.org/tlp/"
}
}
},
"GREEN": {
"distribution": {
"text": "Limited disclosure, recipients can spread this within their community.",
"tlp": {
"label": "GREEN",
"url": "https://www.first.org/tlp/"
}
}
},
"WHITE": {
"distribution": {
"text": "Recipients can spread this to the world, there is no limit on disclosure. ",
"tlp": {
"label": "WHITE",
"url": "https://www.first.org/tlp/"
}
}
}
}
#Choose how VINCE's private and public CSAF documents are mapped with TLP
#If you choose to disable TLP statements in CSAF comment out the MAP dictionary below
CSAF_TLP_MAP = { "PUBLIC": "WHITE", "PRIVATE": "AMBER" }

21 changes: 12 additions & 9 deletions bigvince/storage_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ class PrivateMediaStorage(S3Boto3Storage):
#region_name = "us-east-1"
custom_domain=False
acl='private'
bucket_name = getattr(settings, 'PRIVATE_BUCKET_NAME')

def __init__(self, *args, **kwargs):
kwargs['bucket'] = getattr(settings, 'PRIVATE_BUCKET_NAME')
kwargs['default_acl']='private'
kwargs['acl'] = 'private'
#kwargs['bucket'] = getattr(settings, 'PRIVATE_BUCKET_NAME')
#kwargs['default_acl']='private'
#kwargs['acl'] = 'private'
#if hasattr(settings, 'ATTACHMENT_URL'):
# kwargs['custom_domain'] = settings.ATTACHMENT_URL
#else:
Expand All @@ -59,11 +60,12 @@ class SharedMediaStorage(S3Boto3Storage):
#region_name = "us-east-1"
acl = 'private'
custom_domain = False
bucket_name = getattr(settings, 'VINCE_SHARED_BUCKET')

def __init__(self, *args, **kwargs):
kwargs['bucket'] = getattr(settings, 'VINCE_SHARED_BUCKET')
kwargs['default_acl']='private'
kwargs['acl'] = 'private'
#kwargs['bucket'] = getattr(settings, 'VINCE_SHARED_BUCKET')
#kwargs['default_acl']='private'
#kwargs['acl'] = 'private'
#if hasattr(settings, 'VC_ATTACHMENT_URL'):
# kwargs['custom_domain'] = settings.VC_ATTACHMENT_URL
#else:
Expand All @@ -77,9 +79,10 @@ class VRFReportsStorage(S3Boto3Storage):
custom_domain=False
region_name = settings.AWS_REGION
acl = 'private'
bucket_name = getattr(settings, 'S3_INCOMING_REPORTS')

def __init__(self, *args, **kwargs):
kwargs['bucket'] = getattr(settings, 'S3_INCOMING_REPORTS')
kwargs['default_acl']='private'
kwargs['acl'] = 'private'
#kwargs['bucket'] = getattr(settings, 'S3_INCOMING_REPORTS')
#kwargs['default_acl']='private'
#kwargs['acl'] = 'private'
super(VRFReportsStorage, self).__init__(*args, **kwargs)
79 changes: 52 additions & 27 deletions cogauth/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password
from django.utils.six import iteritems
try:
from django.utils.six import iteritems
except:
from six import iteritems
from django.contrib.auth.models import User
from lib.warrant import Cognito
from lib.warrant.exceptions import ForceChangePasswordException, SoftwareTokenException, SMSMFAException
Expand Down Expand Up @@ -69,7 +72,7 @@ class CognitoUser(Cognito):
def get_user_obj(self, username=None, attribute_list=[], metadata={}, attr_map={}):
user_attrs = cognito_to_dict(attribute_list,CognitoUser.COGNITO_ATTRS)
django_fields = [f.name for f in CognitoUser.user_class._meta.get_fields()]
logger.debug(user_attrs)
logger.debug(f"User attributes in Cognito is {user_attrs}")
extra_attrs = {}
# need to iterate over a copy
for k, v in user_attrs.copy().items():
Expand All @@ -86,39 +89,37 @@ def get_user_obj(self, username=None, attribute_list=[], metadata={}, attr_map={
setattr(user.vinceprofile, k, v)
#logger.debug(f"{k}:{v}")
user.vinceprofile.save()
except:
logger.debug(traceback.format_exc())
logger.debug("vinceprofile probably doesn't exist")
except Exception as e:
logger.debug(f"Vinceprofile probably doesn't exist for user {username}, error returned {e}")
elif settings.VINCE_NAMESPACE == "vince":
try:
for k, v in extra_attrs.items():
setattr(user.usersettings, k, v)
user.usersettings.save()
except:
logger.debug("usersettings probably doesn't exist")
logger.debug(f"usersettings for {username} probably doesn't exist")
else:
try:
user = CognitoUser.user_class.objects.get(username=username)
for k, v in iteritems(user_attrs):
setattr(user, k, v)
user.save()
except CognitoUser.user_class.DoesNotExist:
logger.debug("USER DOES NOT EXIST")
logger.debug(f"USER {username} DOES NOT EXIST")
user = None
if user:
try:
for k, v in extra_attrs.items():
setattr(user.vinceprofile, k, v)
user.vinceprofile.save()
except:
logger.debug("vinceprofile probably does not exist")
logger.debug(traceback.format_exc())
except Exception as e:
logger.debug(f"vinceprofile probably does not exist for {username}, returned error is {e}")
try:
for k, v in extra_attrs.items():
setattr(user.usersettings, k, v)
user.usersettings.save()
except:
logger.debug("usersettings probably doesn't exist")
logger.debug(f"usersettings probably doesn't exist for {username}")
return user

class CognitoAuthenticate(ModelBackend):
Expand All @@ -133,10 +134,8 @@ def authenticate(self, request, username=None, password=None):
username=username)

try:
logger.debug("trying to authenticate %s" % username)
logger.debug(f"trying to authenticate {username}")
cognito_user.authenticate(password)
logger.debug(cognito_user)

except ForceChangePasswordException:
request.session['FORCEPASSWORD']=True
request.session['username']=username
Expand All @@ -156,16 +155,14 @@ def authenticate(self, request, username=None, password=None):
return None
except (Boto3Error, ClientError) as e:
error_code = e.response['Error']['Code']
logger.debug("error: {}".format(e))
logger.debug(error_code)
logger.debug("ERROR AUTHENTICATING")
logger.debug(f"error authenticating user {username} error: {e} {error_code}")
if error_code == "PasswordResetRequiredException":
logger.debug("reset password")
logger.debug(f"reset password needed for {username}")
request.session['RESETPASSWORD']=True
request.session['username']=username
return None
if error_code == "UserNotConfirmedException":
logger.debug("this user did not confirm their account")
logger.debug(f"User {username} did not confirm their account")
#get user
user = User.objects.filter(username=username).first()
if user:
Expand Down Expand Up @@ -242,10 +239,9 @@ def authenticate(self, request, username=None, password=None):
# now we have a cognito user - set session variables and return
if cognito_user:
user = cognito_user.get_user()
logger.debug("USER IS...")
logger.debug(user)
logger.debug(f"USER IS {user}")
else:
logger.debug("RETURNING NONE")
logger.debug("No user found for Cognito auth returning None")
return None

if user:
Expand All @@ -254,10 +250,33 @@ def authenticate(self, request, username=None, password=None):
request.session['REFRESH_TOKEN'] = cognito_user.refresh_token
#request.session.save()

logger.debug("USER IS AUTHENTICATED!")
logger.info(f"USER {user} IS AUTHENTICATED!")
return user


class CognitoAuthenticateAPI(ModelBackend):

def authenticate(self, request):
"""For rest_framework if successfully authenticated using CognitoAuth
the response wil include a tuple (request.user,request.auth)
In case of Session based authentications
request.user will be a Django User instance.
request.auth will be None.
https://www.django-rest-framework.org/api-guide/authentication/
"""
try:
user = CognitoAuthenticate().authenticate(request)
if user:
logger.info(f"API authentication using session for User {user} success")
return user, None
else:
logger.warn(f"Failed API authentication using session for User {user} ")
raise exceptions.AuthenticationFailed(_('Invalid API session attempted'))
except Exception as e:
logger.warn(f"Failed API authentication for session error is {e}")
raise exceptions.AuthenticationFailed(_('Invalid API no session or token header was provided'))




class HashedTokenAuthentication(TokenAuthentication):
Expand Down Expand Up @@ -287,11 +306,17 @@ def authenticate_credentials(self, key):
try:
token = model.objects.select_related('user').get(key=hashed_key)
except model.DoesNotExist:
logger.warn(f"Failed API auth for token that does not exist {key}")
raise exceptions.AuthenticationFailed(_('Invalid token.'))

except Exception as e:
logger.warn(f"Failed API auth for token Error {e}")
raise exceptions.AuthenticationFailed(_('Unknown Token error.'))

if not token.user.is_active:
logger.warn(f"Failed API auth for {token.user} user is inactive or deleted")
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

logger.info(f"Success user {token.user} is authenticated using API Token ")
return (token.user, token)


Expand All @@ -301,7 +326,7 @@ class JSONWebTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
"""Entrypoint for Django Rest Framework"""
jwt_token = self.get_jwt_token(request)
logger.debug(jwt_token)
logger.debug(f"JSOWEb token ookup for {jwt_token}")
if jwt_token is None:
return None

Expand All @@ -311,13 +336,13 @@ def authenticate(self, request):
jwt_payload = token_validator.validate(jwt_token)
except TokenError:
raise exceptions.AuthenticationFailed()
logger.debug(jwt_payload)
logger.debug(f"JSONWeb returned payload is {jwt_payload}")
username=jwt_payload['email']
user = User.objects.get(username=username)
return (user, jwt_token)

def get_jwt_token(self, request):
logger.debug(request.headers)
logger.debug(f"Collected headers for JSONWwebToken as {request.headers}")
auth = get_authorization_header(request).split()
if not auth or smart_text(auth[0].lower()) != "bearer":
return None
Expand Down
1 change: 0 additions & 1 deletion cogauth/templates/cogauth/mfa.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{% extends "vince/login.html" %}
{% load widget_tweaks %}
{% block title %}VINCE{% endblock %}

{% block content_title %}<div class="modal-header"><h3 class="modal-title">Multi-factor Authentication Required</h3></div>{% endblock %}

{% block content %}
Expand Down
3 changes: 2 additions & 1 deletion cogauth/templates/cogauth/mfarequired.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

{% load i18n static %}


{% block extrahead %}
{% endblock %}
{% block content_title %}
<div class="row columns">
<h3>VINCE Multi-factor authentication</h3>
Expand Down
Loading

0 comments on commit d0dbbc9

Please sign in to comment.