Skip to content

Commit

Permalink
Merge branch 'dev' into ruff_pth113
Browse files Browse the repository at this point in the history
  • Loading branch information
manuel-sommer authored Nov 12, 2024
2 parents 6d57f22 + fbbcef0 commit ad649d7
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 14 deletions.
10 changes: 8 additions & 2 deletions dojo/api_v2/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import collections
import json
import logging
import re
Expand Down Expand Up @@ -280,10 +281,10 @@ def _pop_tags(self, validated_data):
return (to_be_tagged, validated_data)


class RequestResponseDict(list):
class RequestResponseDict(collections.UserList):
def __init__(self, *args, **kwargs):
pretty_print = kwargs.pop("pretty_print", True)
list.__init__(self, *args, **kwargs)
collections.UserList.__init__(self, *args, **kwargs)
self.pretty_print = pretty_print

def __add__(self, rhs):
Expand Down Expand Up @@ -2697,6 +2698,11 @@ class ReportGenerateSerializer(serializers.Serializer):
)


class EngagementUpdateJiraEpicSerializer(serializers.Serializer):
epic_name = serializers.CharField(required=False, max_length=200)
epic_priority = serializers.CharField(required=False, allow_null=True)


class TagSerializer(serializers.Serializer):
tags = TagListSerializerField(required=True)

Expand Down
30 changes: 30 additions & 0 deletions dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,36 @@ def download_file(self, request, file_id, pk=None):
# send file
return generate_file_response(file_object)

@extend_schema(
request=serializers.EngagementUpdateJiraEpicSerializer,
responses={status.HTTP_200_OK: serializers.EngagementUpdateJiraEpicSerializer},
)
@action(
detail=True, methods=["post"], permission_classes=[IsAuthenticated],
)
def update_jira_epic(self, request, pk=None):
engagement = self.get_object()
try:

if engagement.has_jira_issue:
jira_helper.update_epic(engagement, **request.data)
response = Response(
{"info": "Jira Epic update query sent"},
status=status.HTTP_200_OK,
)
else:
jira_helper.add_epic(engagement, **request.data)
response = Response(
{"info": "Jira Epic create query sent"},
status=status.HTTP_200_OK,
)
return response
except ValidationError:
return Response(
{"error": "Bad Request!"},
status=status.HTTP_400_BAD_REQUEST,
)


# @extend_schema_view(**schema_with_prefetch())
# Nested models with prefetch make the response schema too long for Swagger UI
Expand Down
3 changes: 3 additions & 0 deletions dojo/finding/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ def prefetch_for_findings(findings, prefetch_type="all", exclude_untouched=True)
if isinstance(
findings, QuerySet,
): # old code can arrive here with prods being a list because the query was already executed
prefetched_findings = prefetched_findings.prefetch_related(
"reviewers",
)
prefetched_findings = prefetched_findings.prefetch_related("reporter")
prefetched_findings = prefetched_findings.prefetch_related(
"jira_issue__jira_project__jira_instance",
Expand Down
13 changes: 11 additions & 2 deletions dojo/jira_link/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1251,7 +1251,9 @@ def close_epic(eng, push_to_jira, **kwargs):
r = requests.post(
url=req_url,
auth=HTTPBasicAuth(jira_instance.username, jira_instance.password),
json=json_data)
json=json_data,
timeout=settings.REQUESTS_TIMEOUT,
)
if r.status_code != 204:
logger.warning(f"JIRA close epic failed with error: {r.text}")
return False
Expand Down Expand Up @@ -1289,7 +1291,14 @@ def update_epic(engagement, **kwargs):
if not epic_name:
epic_name = engagement.name

issue.update(summary=epic_name, description=epic_name)
epic_priority = kwargs.get("epic_priority", None)

jira_issue_update_kwargs = {
"summary": epic_name,
"description": epic_name,
"priority": {"name": epic_priority},
}
issue.update(**jira_issue_update_kwargs)
return True
except JIRAError as e:
logger.exception(e)
Expand Down
8 changes: 7 additions & 1 deletion dojo/management/commands/import_github_languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging

import requests
from django.conf import settings
from django.core.management.base import BaseCommand

from dojo.models import Language_Type
Expand All @@ -22,7 +23,12 @@ def handle(self, *args, **options):
logger.info("Started importing languages from GitHub ...")

try:
deserialized = json.loads(requests.get("https://raw.githubusercontent.com/ozh/github-colors/master/colors.json").text)
deserialized = json.loads(
requests.get(
"https://raw.githubusercontent.com/ozh/github-colors/master/colors.json",
timeout=settings.REQUESTS_TIMEOUT,
).text,
)
except:
msg = "Invalid format"
raise Exception(msg)
Expand Down
12 changes: 9 additions & 3 deletions dojo/notifications/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ def _post_slack_message(channel):
"channel": channel,
"username": get_system_setting("slack_username"),
"text": create_notification_message(event, user, "slack", *args, **kwargs),
})
},
timeout=settings.REQUESTS_TIMEOUT,
)

if "error" in res.text:
logger.error("Slack is complaining. See raw text below.")
Expand Down Expand Up @@ -284,7 +286,9 @@ def send_msteams_notification(event, user=None, *args, **kwargs):
res = requests.request(
method="POST",
url=get_system_setting("msteams_url"),
data=create_notification_message(event, None, "msteams", *args, **kwargs))
data=create_notification_message(event, None, "msteams", *args, **kwargs),
timeout=settings.REQUESTS_TIMEOUT,
)
if res.status_code != 200:
logger.error("Error when sending message to Microsoft Teams")
logger.error(res.status_code)
Expand Down Expand Up @@ -518,7 +522,9 @@ def get_slack_user_id(user_email):
res = requests.request(
method="POST",
url="https://slack.com/api/users.lookupByEmail",
data={"token": get_system_setting("slack_token"), "email": user_email})
data={"token": get_system_setting("slack_token"), "email": user_email},
timeout=settings.REQUESTS_TIMEOUT,
)

user = json.loads(res.text)

Expand Down
6 changes: 5 additions & 1 deletion dojo/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ def update_azure_groups(backend, uid, user=None, social=None, *args, **kwargs):
request_headers = {"Authorization": "Bearer " + token}
if is_group_id(group_from_response):
logger.debug("detected " + group_from_response + " as groupID and will fetch the displayName from microsoft graph")
group_name_request = requests.get((str(soc.extra_data["resource"]) + "/v1.0/groups/" + str(group_from_response) + "?$select=displayName"), headers=request_headers)
group_name_request = requests.get(
(str(soc.extra_data["resource"]) + "/v1.0/groups/" + str(group_from_response) + "?$select=displayName"),
headers=request_headers,
timeout=settings.REQUESTS_TIMEOUT,
)
group_name_request.raise_for_status()
group_name_request_json = group_name_request.json()
group_name = group_name_request_json["displayName"]
Expand Down
8 changes: 8 additions & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@
DD_NOTIFICATIONS_SYSTEM_LEVEL_TRUMP=(list, ["user_mentioned", "review_requested"]),
# When enabled, force the password field to be required for creating/updating users
DD_REQUIRE_PASSWORD_ON_USER=(bool, True),
# For HTTP requests, how long connection is open before timeout
# This settings apply only on requests performed by "requests" lib used in Dojo code (if some included lib is using "requests" as well, this does not apply there)
DD_REQUESTS_TIMEOUT=(int, 30),
)


Expand Down Expand Up @@ -1772,6 +1775,11 @@ def saml2_attrib_map_format(dict):
# ------------------------------------------------------------------------------
NOTIFICATIONS_SYSTEM_LEVEL_TRUMP = env("DD_NOTIFICATIONS_SYSTEM_LEVEL_TRUMP")

# ------------------------------------------------------------------------------
# Timeouts
# ------------------------------------------------------------------------------
REQUESTS_TIMEOUT = env("DD_REQUESTS_TIMEOUT")

# ------------------------------------------------------------------------------
# Ignored Warnings
# ------------------------------------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions dojo/templates/dojo/findings_list_snippet.html
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,11 @@ <h3 class="has-filters">
<th>
{% trans "Planned Remediation" %}
</th>
{% if filter_name != 'Closed' %}
<th>
{% trans "Reviewers" %}
</th>
{% endif %}
{% endblock header %}
</tr>
</thead>
Expand Down Expand Up @@ -699,6 +704,16 @@ <h3 class="has-filters">
<td class="nowrap">
{% if finding.planned_remediation_date %}{{ finding.planned_remediation_date }}{% endif %}
</td>
{% if filter_name != 'Closed' %}
<td class="nowrap">
{% if finding.reviewers %}
{% for reviewer in finding.reviewers.all %}
{{reviewer.get_full_name}}
{% if not forloop.last %}<br>{% endif %}
{% endfor %}
{% endif %}
</td>
{% endif %}
{% endblock body %}
</tr>
{% endfor %}
Expand Down Expand Up @@ -779,6 +794,9 @@ <h3 class="has-filters">
{% endif %}
{ "data": "service" },
{ "data": "planned_remediation_date" },
{% if filter_name != 'Closed' %}
{ "data": "reviewers" },
{% endif %}
];
{% endblock datatables_columns %}
</script>
Expand Down
9 changes: 8 additions & 1 deletion dojo/tools/api_bugcrowd/api_client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from urllib.parse import urlencode

import requests
from django.conf import settings


class BugcrowdAPI:
Expand Down Expand Up @@ -52,7 +53,10 @@ def get_findings(self, program, target):

next = f"{self.bugcrowd_api_url}/submissions?{params_encoded}"
while next != "":
response = self.session.get(url=next)
response = self.session.get(
url=next,
timeout=settings.REQUESTS_TIMEOUT,
)
response.raise_for_status()
if response.ok:
data = response.json()
Expand All @@ -75,12 +79,14 @@ def test_connection(self):
# Request programs
response_programs = self.session.get(
url=f"{self.bugcrowd_api_url}/programs",
timeout=settings.REQUESTS_TIMEOUT,
)
response_programs.raise_for_status()

# Request submissions to validate the org token
response_subs = self.session.get(
url=f"{self.bugcrowd_api_url}/submissions",
timeout=settings.REQUESTS_TIMEOUT,
)
response_subs.raise_for_status()
if response_programs.ok and response_subs.ok:
Expand All @@ -95,6 +101,7 @@ def test_connection(self):
# Request targets to validate the org token
response_targets = self.session.get(
url=f"{self.bugcrowd_api_url}/targets",
timeout=settings.REQUESTS_TIMEOUT,
)
response_targets.raise_for_status()
if response_targets.ok:
Expand Down
5 changes: 5 additions & 0 deletions dojo/tools/api_cobalt/api_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import requests
from django.conf import settings


class CobaltAPI:
Expand Down Expand Up @@ -36,6 +37,7 @@ def get_assets(self):
response = self.session.get(
url=f"{self.cobalt_api_url}/assets?limit=1000",
headers=self.get_headers(),
timeout=settings.REQUESTS_TIMEOUT,
)

if response.ok:
Expand All @@ -56,6 +58,7 @@ def get_findings(self, asset_id):
response = self.session.get(
url=f"{self.cobalt_api_url}/findings?limit=1000&asset={asset_id}",
headers=self.get_headers(),
timeout=settings.REQUESTS_TIMEOUT,
)

if response.ok:
Expand All @@ -72,12 +75,14 @@ def test_connection(self):
response_orgs = self.session.get(
url=f"{self.cobalt_api_url}/orgs",
headers=self.get_headers(),
timeout=settings.REQUESTS_TIMEOUT,
)

# Request assets to validate the org token
response_assets = self.session.get(
url=f"{self.cobalt_api_url}/assets",
headers=self.get_headers(),
timeout=settings.REQUESTS_TIMEOUT,
)

if response_orgs.ok and response_assets.ok:
Expand Down
2 changes: 2 additions & 0 deletions dojo/tools/api_edgescan/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from json.decoder import JSONDecodeError

import requests
from django.conf import settings


class EdgescanAPI:
Expand Down Expand Up @@ -42,6 +43,7 @@ def get_findings(self, asset_ids):
url=url,
headers=self.get_headers(),
proxies=self.get_proxies(),
timeout=settings.REQUESTS_TIMEOUT,
)
response.raise_for_status()
return response.json()
Expand Down
Loading

0 comments on commit ad649d7

Please sign in to comment.