Skip to content

Commit 358c433

Browse files
authored
Merge branch 'dev' into fix-docker-with-override
2 parents 14ec03e + 94a5afd commit 358c433

File tree

125 files changed

+7601
-221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+7601
-221
lines changed

Dockerfile.django

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11

22
# code: language=Dockerfile
3-
FROM python:2
3+
4+
# The code for the build image should be idendical with the code in
5+
# Dockerfile.nginx to use the caching mechanism of Docker.
6+
7+
FROM python:2 as build
48
WORKDIR /app
59
RUN \
610
apt-get -y update && \
@@ -13,7 +17,36 @@ RUN \
1317
rm -rf /var/lib/apt/lists && \
1418
true
1519
COPY requirements.txt ./
16-
RUN pip install -r ./requirements.txt
20+
RUN pip wheel --wheel-dir=/tmp/wheels -r ./requirements.txt
21+
22+
FROM python:2-slim
23+
WORKDIR /app
24+
RUN \
25+
apt-get -y update && \
26+
# ugly fix to install postgresql-client without errors
27+
mkdir -p /usr/share/man/man1 /usr/share/man/man7 && \
28+
apt-get -y install --no-install-recommends \
29+
# libopenjp2-7 libjpeg62 libtiff5 are required by the pillow package
30+
libopenjp2-7 \
31+
libjpeg62 \
32+
libtiff5 \
33+
dnsutils \
34+
mysql-client \
35+
libmariadbclient18 \
36+
# only required for the dbshell (used by the initializer job)
37+
postgresql-client \
38+
&& \
39+
apt-get clean && \
40+
rm -rf /var/lib/apt/lists && \
41+
true
42+
RUN pip install --no-cache-dir --upgrade pip
43+
COPY --from=build /tmp/wheels /tmp/wheels
44+
COPY requirements.txt ./
45+
RUN pip install \
46+
--no-cache-dir \
47+
--no-index \
48+
--find-links=/tmp/wheels \
49+
-r ./requirements.txt
1750
COPY \
1851
docker/entrypoint-celery-beat.sh \
1952
docker/entrypoint-celery-worker.sh \
@@ -39,7 +72,7 @@ USER 1001
3972
ENV \
4073
DD_ADMIN_USER=admin \
4174
42-
DD_ADMIN_PASSWORD= \
75+
DD_ADMIN_PASSWORD='' \
4376
DD_ADMIN_FIRST_NAME=Administrator \
4477
DD_ADMIN_LAST_NAME=User \
4578
DD_ALLOWED_HOSTS="*" \

Dockerfile.nginx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# code: language=Dockerfile
2-
FROM defectdojo/defectdojo-django:latest AS build
2+
3+
# The code for the build image should be idendical with the code in
4+
# Dockerfile.django to use the caching mechanism of Docker.
5+
6+
FROM python:2 as build
7+
WORKDIR /app
8+
RUN \
9+
apt-get -y update && \
10+
apt-get -y install \
11+
dnsutils \
12+
mysql-client \
13+
postgresql-client \
14+
&& \
15+
apt-get clean && \
16+
rm -rf /var/lib/apt/lists && \
17+
true
18+
COPY requirements.txt ./
19+
RUN pip wheel --wheel-dir=/tmp/wheels -r ./requirements.txt
20+
21+
FROM build AS collectstatic
322

423
USER root
524
RUN \
@@ -15,7 +34,18 @@ RUN \
1534
apt-get clean && \
1635
rm -rf /var/lib/apt/lists && \
1736
true
37+
38+
RUN pip install \
39+
--no-cache-dir \
40+
--no-index \
41+
--find-links=/tmp/wheels \
42+
-r ./requirements.txt
43+
1844
COPY components/ ./components/
45+
COPY manage.py ./
46+
COPY dojo/ ./dojo/
47+
RUN \
48+
cp dojo/settings/settings.dist.py dojo/settings/settings.py
1949
RUN \
2050
cd components && \
2151
yarn && \
@@ -24,7 +54,7 @@ RUN \
2454
true
2555

2656
FROM nginx
27-
COPY --from=build /app/static/ /usr/share/nginx/html/static/
57+
COPY --from=collectstatic /app/static/ /usr/share/nginx/html/static/
2858
COPY wsgi_params nginx/nginx.conf /etc/nginx/
2959
COPY docker/entrypoint-nginx.sh /
3060
RUN \

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ should give you an idea of how to use DefectDojo for your own team.
6969
![Slack](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/slack_rgb.png)
7070

7171
Realtime discussion is done in the OWASP Slack Channel, #defectdojo.
72-
[Get Access.](http://owaspslack.com/)
72+
[Get Access.](https://join.slack.com/t/owasp/shared_invite/enQtNjExMTc3MTg0MzU4LTViMDg1MmJiMzMwZGUxZjgxZWQ1MTE0NTBlOTBhNjhhZDIzZTZiNmEwOTJlYjdkMzAxMGVhNDkwNDNiNjZiOWQ)
7373

7474
![Twitter](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/Twitter_Logo.png)
7575

@@ -136,6 +136,9 @@ Proceeds are used for testing, infrastructure, etc.
136136
[![Xing](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/XING_logo.png)](https://corporate.xing.com/en/about-xing/security/)
137137
[![10Security](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/10Security-logo.png)](https://10security.com/services-by-technology/defectdojo-commercial-support/)
138138
[![GCSecurity](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/gc_logo_2018.png)](https://gcsec.com.br/)
139+
[![Timo-Pagel](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/timo-pagel-logo.png )](https://pagel.pro/)
140+
[![SDA-SE](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/sda-se-logo.png)](https://sda-se.com/)
141+
[![Signal-Iduna](https://raw.githubusercontent.com/DefectDojo/Documentation/master/doc/img/signal-iduna.png)](https://signal-iduna.de/)
139142

140143
Interested in becoming a sponsor and having your logo displayed? Please review
141144
our [sponsorship information](SPONSORING.md) or email [email protected]

docker/entrypoint-unit-tests.sh

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22
# Run available unittests with a simple setup
33

44
cd /app
5-
python manage.py makemigrations dojo
6-
python manage.py migrate
7-
exec python manage.py test dojo.unittests --keepdb
5+
6+
./manage.py makemigrations --no-input --check --dry-run || {
7+
cat <<-EOF
8+
9+
********************************************************************************
10+
11+
You made changes to the models without creating a DB migration for them.
12+
13+
**NEVER** change existing migrations, create a new one.
14+
15+
If you're not familiar with migrations in Django, please read the
16+
great documentation thoroughly:
17+
https://docs.djangoproject.com/en/1.11/topics/migrations/
18+
19+
********************************************************************************
20+
21+
EOF
22+
exit 1
23+
}
24+
25+
./manage.py migrate
26+
27+
exec ./manage.py test dojo.unittests

dojo/api_test_files/test.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"engagement": "/api/v1/engagements/96222/",
33
"target_start": "2014-06-07",
44
"target_end": "2014-07-07",
5+
"title": "some title",
56
"test_type": 3
67
}

dojo/api_v2/serializers.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import six
1818
from django.utils.translation import ugettext_lazy as _
1919
import json
20-
20+
from tagging.models import Tag
2121

2222
class TagList(list):
2323
def __init__(self, *args, **kwargs):
@@ -557,13 +557,16 @@ def save(self):
557557
for item in parser.items:
558558
if skip_duplicates:
559559
hash_code = item.compute_hash_code()
560+
560561
if ((test.engagement.deduplication_on_engagement and
561-
Finding.objects.filter(Q(active=True) | Q(false_p=True) | Q(duplicate=True),
562-
test__engagement=test.engagement,
563-
hash_code=hash_code).exists()) or
564-
(Finding.objects.filter(Q(active=True) | Q(false_p=True) | Q(duplicate=True),
565-
test__engagement__product=test.engagement.product,
566-
hash_code=hash_code).exists())):
562+
Finding.objects.filter(Q(active=True) | Q(false_p=True) | Q(duplicate=True),
563+
test__engagement=test.engagement,
564+
hash_code=hash_code).exists()) or
565+
(not test.engagement.deduplication_on_engagement and
566+
Finding.objects.filter(Q(active=True) | Q(false_p=True) | Q(duplicate=True),
567+
test__engagement__product=test.engagement.product,
568+
hash_code=hash_code).exists())):
569+
567570
skipped_hashcodes.append(hash_code)
568571
continue
569572

@@ -649,6 +652,7 @@ def save(self):
649652
old_finding.notes.create(author=self.context['request'].user,
650653
entry="This finding has been automatically closed"
651654
" as it is not present anymore in recent scans.")
655+
Tag.objects.add_tag(old_finding, 'stale')
652656
old_finding.save()
653657
title = 'An old finding has been closed for "{}".' \
654658
.format(test.engagement.product.name)

dojo/api_v2/views.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
from django.http import HttpResponse
2+
from django.shortcuts import get_object_or_404
13
from rest_framework import viewsets, mixins
24
from rest_framework.permissions import DjangoModelPermissions
5+
from rest_framework.decorators import detail_route
36
from django_filters.rest_framework import DjangoFilterBackend
47

8+
from dojo.engagement.services import close_engagement, reopen_engagement
59
from dojo.models import Product, Product_Type, Engagement, Test, Test_Type, Finding, \
610
User, ScanSettings, Scan, Stub_Finding, Finding_Template, \
711
JIRA_Issue, Tool_Product_Settings, Tool_Configuration, Tool_Type, \
@@ -36,6 +40,18 @@ class EngagementViewSet(mixins.ListModelMixin,
3640
'updated', 'threat_model', 'api_test',
3741
'pen_test', 'status', 'product')
3842

43+
@detail_route(methods=["post"])
44+
def close(self, request, pk=None):
45+
eng = get_object_or_404(Engagement.objects, id=pk)
46+
close_engagement(eng)
47+
return HttpResponse()
48+
49+
@detail_route(methods=["post"])
50+
def reopen(self, request, pk=None):
51+
eng = get_object_or_404(Engagement.objects, id=pk)
52+
reopen_engagement(eng)
53+
return HttpResponse()
54+
3955

4056
class FindingTemplatesViewSet(mixins.ListModelMixin,
4157
mixins.RetrieveModelMixin,
@@ -236,8 +252,9 @@ class TestsViewSet(mixins.ListModelMixin,
236252
serializer_class = serializers.TestSerializer
237253
queryset = Test.objects.all()
238254
filter_backends = (DjangoFilterBackend,)
239-
filter_fields = ('id', 'test_type', 'target_start', 'target_end', 'notes',
240-
'percent_complete', 'actual_time', 'engagement')
255+
filter_fields = ('id', 'title', 'test_type', 'target_start',
256+
'target_end', 'notes', 'percent_complete',
257+
'actual_time', 'engagement')
241258

242259
def get_serializer_class(self):
243260
if self.request.method == 'POST':
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.16 on 2019-05-03 18:17
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('dojo', '0001_initial'),
12+
]
13+
14+
operations = [
15+
migrations.AlterField(
16+
model_name='finding',
17+
name='hash_code',
18+
field=models.TextField(blank=True, editable=False, null=True),
19+
),
20+
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.20 on 2019-04-23 09:34
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('dojo', '0002_auto_20190503_1817'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='test',
17+
name='title',
18+
field=models.CharField(blank=True, max_length=255, null=True),
19+
),
20+
]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.20 on 2019-05-06 21:54
3+
from __future__ import unicode_literals
4+
5+
import django.core.validators
6+
from django.db import migrations, models
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('dojo', '0003_test_title'),
13+
]
14+
15+
operations = [
16+
migrations.AddField(
17+
model_name='finding',
18+
name='cve',
19+
field=models.TextField(max_length=20, null=True, validators=[django.core.validators.RegexValidator(message=b"CVE must be entered in the format: 'CVE-9999-9999'. ", regex=b'^CVE-\\d{4}-\\d{4,7}$')]),
20+
),
21+
migrations.AddField(
22+
model_name='finding_template',
23+
name='cve',
24+
field=models.TextField(max_length=20, null=True, validators=[django.core.validators.RegexValidator(message=b"CVE must be entered in the format: 'CVE-9999-9999'. ", regex=b'^CVE-\\d{4}-\\d{4,7}$')]),
25+
),
26+
migrations.AlterField(
27+
model_name='child_rule',
28+
name='match_field',
29+
field=models.CharField(choices=[('id', 'id'), (b'title', b'title'), (b'date', b'date'), (b'cwe', b'cwe'), (b'cve', b'cve'), (b'url', b'url'), (b'severity', b'severity'), (b'description', b'description'), (b'mitigation', b'mitigation'), (b'impact', b'impact'), (b'steps_to_reproduce', b'steps_to_reproduce'), (b'severity_justification', b'severity_justification'), (b'references', b'references'), (b'test', b'test'), (b'is_template', b'is_template'), (b'active', b'active'), (b'verified', b'verified'), (b'false_p', b'false_p'), (b'duplicate', b'duplicate'), (b'duplicate_finding', b'duplicate_finding'), (b'out_of_scope', b'out_of_scope'), (b'under_review', b'under_review'), (b'review_requested_by', b'review_requested_by'), (b'under_defect_review', b'under_defect_review'), (b'defect_review_requested_by', b'defect_review_requested_by'), (b'thread_id', b'thread_id'), (b'mitigated', b'mitigated'), (b'mitigated_by', b'mitigated_by'), (b'reporter', b'reporter'), (b'numerical_severity', b'numerical_severity'), (b'last_reviewed', b'last_reviewed'), (b'last_reviewed_by', b'last_reviewed_by'), (b'line_number', b'line_number'), (b'sourcefilepath', b'sourcefilepath'), (b'sourcefile', b'sourcefile'), (b'param', b'param'), (b'payload', b'payload'), (b'hash_code', b'hash_code'), (b'line', b'line'), (b'file_path', b'file_path'), (b'static_finding', b'static_finding'), (b'dynamic_finding', b'dynamic_finding'), (b'created', b'created'), (b'scanner_confidence', b'scanner_confidence')], max_length=200),
30+
),
31+
migrations.AlterField(
32+
model_name='rule',
33+
name='applied_field',
34+
field=models.CharField(choices=[('id', 'id'), (b'title', b'title'), (b'date', b'date'), (b'cwe', b'cwe'), (b'cve', b'cve'), (b'url', b'url'), (b'severity', b'severity'), (b'description', b'description'), (b'mitigation', b'mitigation'), (b'impact', b'impact'), (b'steps_to_reproduce', b'steps_to_reproduce'), (b'severity_justification', b'severity_justification'), (b'references', b'references'), (b'test', b'test'), (b'is_template', b'is_template'), (b'active', b'active'), (b'verified', b'verified'), (b'false_p', b'false_p'), (b'duplicate', b'duplicate'), (b'duplicate_finding', b'duplicate_finding'), (b'out_of_scope', b'out_of_scope'), (b'under_review', b'under_review'), (b'review_requested_by', b'review_requested_by'), (b'under_defect_review', b'under_defect_review'), (b'defect_review_requested_by', b'defect_review_requested_by'), (b'thread_id', b'thread_id'), (b'mitigated', b'mitigated'), (b'mitigated_by', b'mitigated_by'), (b'reporter', b'reporter'), (b'numerical_severity', b'numerical_severity'), (b'last_reviewed', b'last_reviewed'), (b'last_reviewed_by', b'last_reviewed_by'), (b'line_number', b'line_number'), (b'sourcefilepath', b'sourcefilepath'), (b'sourcefile', b'sourcefile'), (b'param', b'param'), (b'payload', b'payload'), (b'hash_code', b'hash_code'), (b'line', b'line'), (b'file_path', b'file_path'), (b'static_finding', b'static_finding'), (b'dynamic_finding', b'dynamic_finding'), (b'created', b'created'), (b'scanner_confidence', b'scanner_confidence')], max_length=200),
35+
),
36+
migrations.AlterField(
37+
model_name='rule',
38+
name='match_field',
39+
field=models.CharField(choices=[('id', 'id'), (b'title', b'title'), (b'date', b'date'), (b'cwe', b'cwe'), (b'cve', b'cve'), (b'url', b'url'), (b'severity', b'severity'), (b'description', b'description'), (b'mitigation', b'mitigation'), (b'impact', b'impact'), (b'steps_to_reproduce', b'steps_to_reproduce'), (b'severity_justification', b'severity_justification'), (b'references', b'references'), (b'test', b'test'), (b'is_template', b'is_template'), (b'active', b'active'), (b'verified', b'verified'), (b'false_p', b'false_p'), (b'duplicate', b'duplicate'), (b'duplicate_finding', b'duplicate_finding'), (b'out_of_scope', b'out_of_scope'), (b'under_review', b'under_review'), (b'review_requested_by', b'review_requested_by'), (b'under_defect_review', b'under_defect_review'), (b'defect_review_requested_by', b'defect_review_requested_by'), (b'thread_id', b'thread_id'), (b'mitigated', b'mitigated'), (b'mitigated_by', b'mitigated_by'), (b'reporter', b'reporter'), (b'numerical_severity', b'numerical_severity'), (b'last_reviewed', b'last_reviewed'), (b'last_reviewed_by', b'last_reviewed_by'), (b'line_number', b'line_number'), (b'sourcefilepath', b'sourcefilepath'), (b'sourcefile', b'sourcefile'), (b'param', b'param'), (b'payload', b'payload'), (b'hash_code', b'hash_code'), (b'line', b'line'), (b'file_path', b'file_path'), (b'static_finding', b'static_finding'), (b'dynamic_finding', b'dynamic_finding'), (b'created', b'created'), (b'scanner_confidence', b'scanner_confidence')], max_length=200),
40+
),
41+
]

0 commit comments

Comments
 (0)