Skip to content

Commit

Permalink
Version 2.0.6a (#89)
Browse files Browse the repository at this point in the history
* Updates to 2.0.6 related updates

* Minor updates 2.0.6a
  • Loading branch information
sei-vsarvepalli authored Feb 13, 2023
1 parent 2bed565 commit 95e3b12
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 21 deletions.
29 changes: 22 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
# Contributing to VINCE

### Reporting Problems and Asking Questions
### Reporting Problems and Asking Questions and Requesting Features

You can report a bug, feature request, or other issue
in this GitHub project. VINCE users can also send
[feedback](https://kb.cert.org/vince/comm/sendmsg/8/)
through the Private Message feature.
through the Private Message feature. When requesting
a new feature, provide as much details as possible for
the feature at hand. If the feature is relevant to a
specific community, consider making the feature modular
using `settings.py` as the defacto place to configure
enable/disable of all such flexible features.

Our GitHub repository has
[Private Advisories](https://github.com/CERTCC/VINCE/security/advisories) feature
enabled. You can use this to privately report security issues found in
our software. You can also do so using VINCE
[Private Message](https://kb.cert.org/vince/comm/sendmsg/8/), if you have an
active VINCE account.


### Contributing Code Changes
Expand All @@ -20,11 +32,14 @@ resembling an open source public release.
As a consequence, it is difficult for us to coordinate external pull
requests with our internal code base, and we have not completely
worked out a process for doing so. If you would like to contribute
code to VINCE, please do so by submitting a pull request and we'll
work with you to get it accepted into the public code.

We do plan to commit non-urgent and new feature changes on a monthly
cadence.
code to VINCE, please make sure you reference at least one GitHub
issue either opened by you or another GitHub user that identifies
either the problem/bugfix or a new feature/capability being introduced.
We require all Pull Requests to be signed using a GPG verified certificate
that is part of your GitHub profile. There is a specific `development`
branch where we accept features that require compatibility testing with
our `main` branch. We do plan to commit non-urgent and new feature changes
on a monthly cadence.

### Terms of Submission

Expand Down
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ of AWS services such as Cognito, S3, ElasticBeanstalk, Cloudfront, SQS, SNS,
and SES. VINCE uses the python library,
[warrant](https://github.com/capless/warrant), for AWS Cognito
authentication. [Warrant](https://github.com/capless/warrant) has been
slightly modified and is included with VINCE.
slightly modified and is included with VINCE.

VINCE also uses and includes
the [django-bakery](https://github.com/palewire/django-bakery) project to
Expand All @@ -38,6 +38,41 @@ via an AWS S3 bucket. The
[django-bakery](https://github.com/palewire/django-bakery) project has been
modified to generate the flat files in memory versus using the filesystem.

VINCE also has a [development](https://github.com/CERTCC/VINCE/tree/development)
branch which can be run using [LocalStack](https://localstack.cloud).


### Architecture

VINCE follows a traditional Django's `Model-Template-View-Controller` for most part.
VINCE's 3-Tier setup is designed to work with Web/Presentation Tier (Amazon CloudFront),
Application Tier (Amazon ElasticBeanStalk) and Database Tier (Amazon RDS). All these
components can be mimicked (or replaced) to either use LocalStack or individual
open-source software for each of these tiers. VINCE's services interface to Storage (Amazon S3)
Notifications (Amazon SNS), Queueing (Amazon SQS) and Messaging (Amazon SES) are all modular
and can be adapted to either LocalStack or other python3+Django supported modules. VINCE's
Identity Management is defaulted to Cognito - this also can be modified to use other Identity
Providers. Cognito identity is also tied to few modules such as S3 buckets used for file
storage, including both uploads and downloads. These can be mimicked using LocalStack. Code
updates may be required in cases of file interactions.

VINCE application is made of three individual applications and databases.
* VINCETRACK application (database vincetrack) launched from (vince/)[vince/] folder.
* VINCECOMM application (database vincecomm) launched from (vinny/)[vinny/].
* VINCEPUB application (database vincepub) launched from (vincepub/)[vincepub/].

The VINCETRACK application requires access to all three database schemas and tables.
The VINCETRACK app is meant for `Coordinators and Administrators` by default deisgned to be in
a group labeled as `Coordinator` or as setup in `bigvince.settings.COGNITO_ADMIN_GROUP`
with higher privileges. The VINCECOMM and VINCEPUB applications have access to their respective schemas.
The VINCECOMM applications is acessible to Vendors, Finders
(Security Researchers) as well as other stakeholders that are registered, verified and have been approved. The
VINCEPUB application provides publicly available publications and reports that unauthenticated
users. Each application can also be further protected by network access controls as desired to
reduce the risk of exposure.

[<img src="VINCE_Infrastructure.png" width="100%"></A>](./VINCE_Infrastructure.png)


### Local Install

Expand Down Expand Up @@ -79,9 +114,8 @@ DATABASE_PASSWORD=PASSWORD

5. Create secret key
```
python3 -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
python3 -c 'from django.utils.crypto import get_random_string; chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#%^&*(-_=+)"; print(get_random_string(50, chars));';
```
Swap out any "$" characters if they exist. $ characters mess with API key generation. Or continue to regenerate until you get a key without a "$"
Add it to bigvince/.env

6. Edit bigvince/settings_.py as needed with your settings. Important settings to pay attention to:
Expand Down Expand Up @@ -109,6 +143,7 @@ SUPERUSER

7. Run migrations
```
python manage.py makemigrations
python manage.py migrate
python manage.py migrate --database=vincecomm
python manage.py migrate --database=vincepub
Expand Down
Binary file added Vince_Infrastructure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 44 additions & 2 deletions lib/vince/mutelib.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib.auth.models import User
from django.contrib.auth.models import User,Group
from vinny.views import VinceProfile as vp

from vinny.models import Case, CaseVulnerability, CaseMemberStatus, CaseMember


def mute_user(useremail,case_id,interactive=False):
Expand Down Expand Up @@ -37,3 +37,45 @@ def mute_user(useremail,case_id,interactive=False):
print(l._get_settings())
return 1

def mute_case_not_affected(case_id,interactive=False):
""" Mute case for all users who are participating in a Case but
have already indicated that they are "Not Affected" - the assumption
is they do not want to hear about this Case any more due to their
status being "Not Affected"
"""
c = Case.objects.get(id=int(case_id))
if not c:
if interactive:
print("No Case found in VinceComm")
return -1
vul = CaseVulnerability.objects.filter(case=c)
if not vul:
if interactive:
print("No Vulnerabilities for this Case found in VinceComm")
return -1
x = CaseMemberStatus.objects.filter(vulnerability__in=vul,status=2)
f = CaseMember.objects.filter(id__in=x.values_list('member'))
user_list = User.objects.using('vincecomm').filter(groups__in=f.values_list('group'))
t = 'muted_cases'
updated = 0
for q in user_list:
l = vp.objects.get(user=q)
d = q.vinceprofile.settings.copy()
if t in d and case_id in d[t]:
if interactive:
print(f"Already muted {case_id} {q}")
continue
else:
if t in d:
if interactive:
print(f"Adding to muted_cases {q}")
d[t] += [case_id]
else:
if interactive:
print(f"Creating a new muted_case for user {q}")
d[t] = [case_id]
l._set_settings(d)
l.save()
updated = updated + 1
return updated

4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ chardet==5.0.0
charset-normalizer==2.1.1
click==8.1.3
colorama==0.4.4
cryptography==38.0.3
cryptography==39.0.1
cvelib==1.1.0
Deprecated==1.2.13
dictdiffer==0.9.0
Django==3.2.16
Django==3.2.17
django-appconf==1.0.5
django-countries==7.4.2
django-environ==0.9.0
Expand Down
28 changes: 26 additions & 2 deletions vince/static/vince/js/vince.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,11 @@ $(function () {
return JSON.stringify(d,null,'\t')
}
function msg_card(el,msg,level) {
$(el).html(msg).removeClass('hide').addClass('card-'+level);
$(el).html(msg).removeClass().addClass('card-' + level +
' dashboard-nav-card');
if(level == "bad") {
$(el).on('click',function() { $('#xmodal').foundation('close'); })
}
}
}
function load_cvedata(cvetype) {
$('a.cvetab').attr("aria-selected","false");
Expand Down Expand Up @@ -532,6 +533,29 @@ $(function () {
let btnSubmit = $('<button>').addClass('button primary')
.html("Publish");
btnSubmit.on('click',function() {
let cve5 = $('#cve5data').val();
try {
let cve5Obj = JSON.parse(cve5);
if(deepGet(cve5Obj,"containers.cna")) {
/* Remove non cna container fields */
cve5 = json_pretty(cve5Obj.containers.cna);
cve5Obj = JSON.parse(cve5);
$('#cve5data').val(cve5);
}
["affected.0.product",
"affected.0.versions.0.version",
"affected.0.vendor",
"descriptions.0.lang",
"descriptions.0.value",
"references.0.url"].forEach(function(x) {
if(!deepGet(cve5Obj,x))
throw new Error("Element " +
x + " is required");
});
} catch(err) {
msg_card(el,"CVE data incorrect: " + err,"bad");
return;
}
let msg = "This CVE will go fully public immediately! "+
"\nAre you Sure?";
el.addClass('hide');
Expand Down
6 changes: 3 additions & 3 deletions vince/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ def process_query_for_tags(s):
return ret

def process_query(s, live=True):
query = re.sub(r'[!\'()|&<>]', ' ', s).strip()
query = re.sub(r'[!\'()|&<>:]', ' ', s).strip()
# get rid of empty quotes
query = re.sub(r'""', '', query)
if query == '"':
Expand Down Expand Up @@ -4757,7 +4757,7 @@ def form_valid(self, form):
crfup.save()

elif int(form.cleaned_data['send_email']) == 3:
logger.debug(f"send message to VINCE User {vc_user}")
logger.debug(f"send message to VINCE User {ticket.submitter_email}")
user_lookup = User.objects.using('vincecomm').filter(email=ticket.submitter_email).first()
sender = User.objects.using('vincecomm').filter(email=self.request.user.email).first()
subject = f"[{ticket.ticket_for_url}] {email_template.subject} {ticket.title}"
Expand Down Expand Up @@ -10342,7 +10342,7 @@ def get_context_data(self, **kwargs):
'pgp_formset': self.PgPFormSet(prefix='pgp', queryset=pgp, instance=contact)}
#'email_formset': self.EmailFormSet(prefix='email', queryset=email, instance=contact)}
context['groups'] = GroupMember.objects.filter(contact=self.kwargs['pk'])
context['form'] = self.form_class(initial=Contact.objects.filter(id=self.kwargs['pk']).values()[0])
context['form'] = self.form_class(initial=contact)
context['form'].fields['vtype'].choices = [('User', 'User'), ('Vendor', 'Vendor'), ('Coordinator', 'Coordinator')]
context['form'].fields['vtype'].initial = contact.vendor_type
context['contact'] = contact
Expand Down
1 change: 1 addition & 0 deletions vinny/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
re_path('^sendmsg/(?P<type>[1-9]|10)?/$', views.SendMessageView.as_view(), name='sendmsg'),
re_path('^sendmsg/(?P<type>[2])/(?P<case>\d+)/$', views.SendMessageView.as_view(), name='sendmsg'),
path('sendmsg/all/', views.SendMessageAllView.as_view(), name='sendmsgall'),
path('auto/api/allvendors/', views.autocomplete_allvendors, name='all_vendors'),
path('auto/api/vlookup/', views.VendorLookupView.as_view(), name='vendorlookup'),
path('auto/api/vendors/', views.autocomplete_vendor, name='auto_vendor'),
path('auto/api/users/', views.autocomplete_users, name='auto_user'),
Expand Down
13 changes: 11 additions & 2 deletions vinny/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,15 @@ def autocomplete_coordinators(request, pk):

return HttpResponse([], 'application/json')

@login_required(login_url="vinny:login")
@user_passes_test(is_not_pending, login_url="vinny:login")
def autocomplete_allvendors(request):
qs = VinceCommContact.objects.filter(vendor_type='Vendor',active=True).values('pk','vendor_name')
ed = ED(base64.b64encode(settings.SECRET_KEY.encode()))
#Hide uuid and pk fields - allow usage in specific Cases only
data = list(map(lambda x: {"euid": ed.encrypt(str(x['pk'])), "vendor_name" : x["vendor_name"]}, qs))
return HttpResponse(json.dumps(data,default=str), 'application/json')


@login_required(login_url="vinny:login")
@user_passes_test(is_in_group_vincetrack, login_url='vinny:login')
Expand Down Expand Up @@ -598,7 +607,7 @@ def get(self, request, *args, **kwargs):
if not(mime_type):
mime_type = 'application/octet-stream'
response = HttpResponseRedirect(report.user_file.url, content_type = mime_type)
filename = vinceutils.safe_filename(report.user_file.name,file_uuid,mime_type)
filename = vinceutils.safe_filename(report.user_file.name,None,mime_type)
response['ResponseContentDisposition'] = f"attachment; filename=\"{filename}\""
response["Content-type"] = mime_type
response["Cache-Control"] = "must-revalidate"
Expand Down Expand Up @@ -3147,7 +3156,7 @@ def get_context_data(self, **kwargs):

def process_query(s):

query = re.sub(r'[!\'()|&]', ' ', s).strip()
query = re.sub(r'[!\'()|&:]', ' ', s).strip()
if query.startswith(settings.CASE_IDENTIFIER):
query = query[len(settings.CASE_IDENTIFIER):]
if query:
Expand Down

0 comments on commit 95e3b12

Please sign in to comment.