Skip to content

Commit 01790e5

Browse files
hblankenshipcneill
andauthored
Make the number of request/response pairs returned by the API configurable (#9967)
* limit req response via setting * add unittest * update running test documentation * also must do here * fix linting, add urls.py * trailing space in a comment... * switch back to finding - different test uses it * change test data to not break * reset data, use my own * Update dojo/settings/settings.dist.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com>
1 parent a883290 commit 01790e5

8 files changed

Lines changed: 1177 additions & 6 deletions

File tree

dojo/api_v2/serializers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1806,8 +1806,11 @@ def build_relational_field(self, field_name, relation_info):
18061806

18071807
@extend_schema_field(BurpRawRequestResponseSerializer)
18081808
def get_request_response(self, obj):
1809-
# burp_req_resp = BurpRawRequestResponse.objects.filter(finding=obj)
1809+
# Not necessarily Burp scan specific - these are just any request/response pairs
18101810
burp_req_resp = obj.burprawrequestresponse_set.all()
1811+
var = settings.MAX_REQRESP_FROM_API
1812+
if var > -1:
1813+
burp_req_resp = burp_req_resp[:var]
18111814
burp_list = []
18121815
for burp in burp_req_resp:
18131816
request = burp.get_request()

dojo/api_v2/views.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,12 @@ def request_response(self, request, pk=None):
10041004
return Response(
10051005
burps.errors, status=status.HTTP_400_BAD_REQUEST
10061006
)
1007-
1007+
# Not necessarily Burp scan specific - these are just any request/response pairs
10081008
burp_req_resp = BurpRawRequestResponse.objects.filter(finding=finding)
1009+
var = settings.MAX_REQRESP_FROM_API
1010+
if var > -1:
1011+
burp_req_resp = burp_req_resp[:var]
1012+
10091013
burp_list = []
10101014
for burp in burp_req_resp:
10111015
request = burp.get_request()

dojo/fixtures/unit_limit_reqresp.json

Lines changed: 376 additions & 0 deletions
Large diffs are not rendered by default.

dojo/settings/settings.dist.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
# maximum number of result in search as search can be an expensive operation
201201
DD_SEARCH_MAX_RESULTS=(int, 100),
202202
DD_SIMILAR_FINDINGS_MAX_RESULTS=(int, 25),
203+
# The maximum number of request/response pairs to return from the API. Values <0 return all pairs.
204+
DD_MAX_REQRESP_FROM_API=(int, -1),
203205
DD_MAX_AUTOCOMPLETE_WORDS=(int, 20000),
204206
DD_JIRA_SSL_VERIFY=(bool, True),
205207
# You can set extra Jira issue types via a simple env var that supports a csv format, like "Work Item,Vulnerability"
@@ -233,7 +235,6 @@
233235
DD_FEATURE_FINDING_GROUPS=(bool, True),
234236
DD_JIRA_TEMPLATE_ROOT=(str, 'dojo/templates/issue-trackers'),
235237
DD_TEMPLATE_DIR_PREFIX=(str, 'dojo/templates/'),
236-
237238
# Initial behaviour in Defect Dojo was to delete all duplicates when an original was deleted
238239
# New behaviour is to leave the duplicates in place, but set the oldest of duplicates as new original
239240
# Set to True to revert to the old behaviour where all duplicates are deleted
@@ -599,6 +600,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
599600

600601
SEARCH_MAX_RESULTS = env('DD_SEARCH_MAX_RESULTS')
601602
SIMILAR_FINDINGS_MAX_RESULTS = env('DD_SIMILAR_FINDINGS_MAX_RESULTS')
603+
MAX_REQRESP_FROM_API = env('DD_MAX_REQRESP_FROM_API')
602604
MAX_AUTOCOMPLETE_WORDS = env('DD_MAX_AUTOCOMPLETE_WORDS')
603605

604606
LOGIN_EXEMPT_URLS = (

dojo/urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
v2_api.register(r'engagements', EngagementViewSet)
8282
v2_api.register(r'development_environments', DevelopmentEnvironmentViewSet)
8383
v2_api.register(r'finding_templates', FindingTemplatesViewSet)
84-
v2_api.register(r'findings', FindingViewSet)
84+
v2_api.register(r'findings', FindingViewSet, basename='finding')
8585
v2_api.register(r'jira_configurations', JiraInstanceViewSet) # backwards compatibility
8686
v2_api.register(r'jira_instances', JiraInstanceViewSet)
8787
v2_api.register(r'jira_finding_mappings', JiraIssuesViewSet)

readme-docs/DOCKER.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,26 @@ The integration-tests are under `tests`
335335

336336

337337
## Running the unit tests
338+
339+
### All tests
338340
This will run all unit-tests and leave the uwsgi container up:
339341

340342
```
341343
docker/setEnv.sh unit_tests
342344
./dc-up.sh
343345
```
344-
Enter the container to run more tests:
345346

347+
### Limited tests
348+
If you want to enter the container to run more tests or a single test case, leave setEnv in normal or dev mode:
349+
```
350+
docker/setEnv.sh dev
351+
./dc-up.sh
352+
```
353+
Then
346354
```
347-
docker-compose exec uwsgi bash
355+
docker ps
356+
#find the name of the uwsgi container from the above command
357+
docker exec -ti [container-name] bash
348358
```
349359
Rerun all the tests:
350360

unittests/scans/burp_api/many_reqresp.json

Lines changed: 734 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from rest_framework.test import APITestCase, APIClient
2+
from django.urls import reverse
3+
from rest_framework.authtoken.models import Token
4+
from django.conf import settings
5+
6+
7+
class APILimitReqRespPairsTest(APITestCase):
8+
"""
9+
Test the MAX_REQRESP_FROM_API setting for /api/v2/findings/{id}/request_response/
10+
"""
11+
12+
fixtures = ['unit_limit_reqresp.json']
13+
14+
def setUp(self: object):
15+
token = Token.objects.get(user__username='admin')
16+
self.client = APIClient()
17+
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
18+
19+
def assertReqrespValue(self: object, value: int, expect_notequal: bool = False) -> None:
20+
settings.MAX_REQRESP_FROM_API = value
21+
r = self.client.get(reverse('finding-list'), format='json')
22+
results = r.json()['results']
23+
# get finding with id 8
24+
finding = self.getFinding(8, results)
25+
if expect_notequal:
26+
self.assertNotEqual(len(finding['request_response']['req_resp']), value)
27+
else:
28+
self.assertEqual(len(finding['request_response']['req_resp']), value)
29+
30+
def getFinding(self: object, idn: int, results: list) -> dict:
31+
for result in results:
32+
if result['id'] == idn:
33+
return result
34+
return None
35+
36+
def test_reqresp(self: object) -> None:
37+
self.assertReqrespValue(5)
38+
self.assertReqrespValue(10)
39+
self.assertReqrespValue(18) # actual number of reqresp
40+
self.assertReqrespValue(100, True) # more than the number in the request
41+
self.assertReqrespValue(-1, True) # default value of MAX_REQRESP_FROM_API
42+
self.assertReqrespValue(-100, True) # crazy negative value

0 commit comments

Comments
 (0)