Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 8 additions & 58 deletions dojo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
from dojo.endpoint.utils import endpoint_filter, endpoint_get_or_create, validate_endpoints_to_add
from dojo.engagement.queries import get_authorized_engagements
from dojo.finding.queries import get_authorized_findings
from dojo.github.ui.forms import ( # noqa: F401 -- backward compat
DeleteGITHUBConfForm,
ExpressGITHUBForm,
GITHUB_IssueForm,
GITHUB_Product_Form,
GITHUBFindingForm,
GITHUBForm,
)
from dojo.group.queries import get_authorized_groups, get_group_member_roles
from dojo.jira import services as jira_services
from dojo.jira.forms import ( # noqa: F401 backward compat
Expand Down Expand Up @@ -79,9 +87,6 @@
Finding_Group,
Finding_Template,
General_Survey,
GITHUB_Conf,
GITHUB_Issue,
GITHUB_PKey,
Global_Role,
Note_Type,
Notes,
Expand Down Expand Up @@ -2801,42 +2806,6 @@ class Meta:
fields = ["id"]


class GITHUB_IssueForm(forms.ModelForm):

class Meta:
model = GITHUB_Issue
exclude = ["product"]


class GITHUBForm(forms.ModelForm):
api_key = forms.CharField(widget=forms.PasswordInput, required=True)

class Meta:
model = GITHUB_Conf
exclude = ["product"]


class DeleteGITHUBConfForm(forms.ModelForm):
id = forms.IntegerField(required=True,
widget=forms.widgets.HiddenInput())

class Meta:
model = GITHUB_Conf
fields = ["id"]


class ExpressGITHUBForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, required=True)
issue_key = forms.CharField(required=True, help_text="A valid issue ID is required to gather the necessary information.")

class Meta:
model = GITHUB_Conf
exclude = ["product", "epic_name_id", "open_status_key",
"close_status_key", "info_mapping_severity",
"low_mapping_severity", "medium_mapping_severity",
"high_mapping_severity", "critical_mapping_severity", "finding_text"]


class Benchmark_Product_SummaryForm(forms.ModelForm):

class Meta:
Expand Down Expand Up @@ -3222,25 +3191,6 @@ class Meta:
# fields = ['selenium_script']


class GITHUB_Product_Form(forms.ModelForm):
git_conf = forms.ModelChoiceField(queryset=GITHUB_Conf.objects.all(), label="GITHUB Configuration", required=False)

class Meta:
model = GITHUB_PKey
exclude = ["product"]


class GITHUBFindingForm(forms.Form):
def __init__(self, *args, **kwargs):
self.enabled = kwargs.pop("enabled")
super().__init__(*args, **kwargs)
self.fields["push_to_github"] = forms.BooleanField()
self.fields["push_to_github"].required = False
self.fields["push_to_github"].help_text = "Checking this will overwrite content of your Github issue, or create one."

push_to_github = forms.BooleanField(required=False)


class LoginBanner(forms.Form):
banner_enable = forms.BooleanField(
label="Enable login banner",
Expand Down
1 change: 1 addition & 0 deletions dojo/github/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import dojo.github.admin # noqa: F401
15 changes: 15 additions & 0 deletions dojo/github/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.contrib import admin

from dojo.github.models import (
GITHUB_Clone,
GITHUB_Conf,
GITHUB_Details_Cache,
GITHUB_Issue,
GITHUB_PKey,
)

admin.site.register(GITHUB_Conf)
admin.site.register(GITHUB_Issue)
admin.site.register(GITHUB_Clone)
admin.site.register(GITHUB_Details_Cache)
admin.site.register(GITHUB_PKey)
45 changes: 45 additions & 0 deletions dojo/github/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from django.db import models
from django.utils.translation import gettext as _

from dojo.models import Finding, Product


class GITHUB_Conf(models.Model):
configuration_name = models.CharField(max_length=2000, help_text=_("Enter a name to give to this configuration"), default="")
api_key = models.CharField(max_length=2000, help_text=_("Enter your Github API Key"), default="")

def __str__(self):
return self.configuration_name


class GITHUB_Issue(models.Model):
issue_id = models.CharField(max_length=200)
issue_url = models.URLField(max_length=2000, verbose_name=_("GitHub issue URL"))
finding = models.OneToOneField(Finding, null=True, blank=True, on_delete=models.CASCADE)

def __str__(self):
return str(self.issue_id) + "| GitHub Issue URL: " + str(self.issue_url)


class GITHUB_Clone(models.Model):
github_id = models.CharField(max_length=200)
github_clone_id = models.CharField(max_length=200)


class GITHUB_Details_Cache(models.Model):
github_id = models.CharField(max_length=200)
github_key = models.CharField(max_length=200)
github_status = models.CharField(max_length=200)
github_resolution = models.CharField(max_length=200)


class GITHUB_PKey(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)

git_project = models.CharField(max_length=200, blank=True, verbose_name=_("Github project"), help_text=_("Specify your project location. (:user/:repo)"))
git_conf = models.ForeignKey(GITHUB_Conf, verbose_name=_("Github Configuration"),
null=True, blank=True, on_delete=models.CASCADE)
git_push_notes = models.BooleanField(default=False, blank=True, help_text=_("Notes added to findings will be automatically added to the corresponding github issue"))

def __str__(self):
return self.product.name + " | " + self.git_project
16 changes: 10 additions & 6 deletions dojo/github.py → dojo/github/services.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
# python
import logging
import sys

from django.template.loader import render_to_string

# External libs
from github import Auth, Github

# Dojo related imports
from dojo.models import Engagement, GITHUB_Issue, GITHUB_PKey, Product
from dojo.github.models import GITHUB_Issue, GITHUB_PKey
from dojo.models import Engagement, Product

# Create global
logger = logging.getLogger(__name__)


def validate_github_credentials(api_key):
"""Verify a GitHub API key by fetching the authenticated user. Raises on failure."""
g = Github(api_key)
user = g.get_user()
logger.debug("Using user " + user.login)
return user.login


def reopen_external_issue_github(find, note, prod, eng):
# Ensure the system setting for GitHub integration is enabled
from dojo.utils import get_system_setting # noqa: PLC0415 circular import
Expand Down
File renamed without changes.
58 changes: 58 additions & 0 deletions dojo/github/ui/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from django import forms

from dojo.github.models import GITHUB_Conf, GITHUB_Issue, GITHUB_PKey


class GITHUB_IssueForm(forms.ModelForm):

class Meta:
model = GITHUB_Issue
exclude = ["product"]


class GITHUBForm(forms.ModelForm):
api_key = forms.CharField(widget=forms.PasswordInput, required=True)

class Meta:
model = GITHUB_Conf
exclude = ["product"]


class DeleteGITHUBConfForm(forms.ModelForm):
id = forms.IntegerField(required=True,
widget=forms.widgets.HiddenInput())

class Meta:
model = GITHUB_Conf
fields = ["id"]


class ExpressGITHUBForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput, required=True)
issue_key = forms.CharField(required=True, help_text="A valid issue ID is required to gather the necessary information.")

class Meta:
model = GITHUB_Conf
exclude = ["product", "epic_name_id", "open_status_key",
"close_status_key", "info_mapping_severity",
"low_mapping_severity", "medium_mapping_severity",
"high_mapping_severity", "critical_mapping_severity", "finding_text"]


class GITHUB_Product_Form(forms.ModelForm):
git_conf = forms.ModelChoiceField(queryset=GITHUB_Conf.objects.all(), label="GITHUB Configuration", required=False)

class Meta:
model = GITHUB_PKey
exclude = ["product"]


class GITHUBFindingForm(forms.Form):
def __init__(self, *args, **kwargs):
self.enabled = kwargs.pop("enabled")
super().__init__(*args, **kwargs)
self.fields["push_to_github"] = forms.BooleanField()
self.fields["push_to_github"].required = False
self.fields["push_to_github"].help_text = "Checking this will overwrite content of your Github issue, or create one."

push_to_github = forms.BooleanField(required=False)
File renamed without changes.
12 changes: 4 additions & 8 deletions dojo/github_issue_link/views.py → dojo/github/ui/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt
from github import Github

from dojo.authorization.authorization_decorators import user_is_configuration_authorized

# Local application/library imports
from dojo.forms import DeleteGITHUBConfForm, GITHUBForm
from dojo.models import GITHUB_Conf
from dojo.github.models import GITHUB_Conf
from dojo.github.services import validate_github_credentials
from dojo.github.ui.forms import DeleteGITHUBConfForm, GITHUBForm
from dojo.utils import add_breadcrumb, get_setting

logger = logging.getLogger(__name__)
Expand All @@ -33,9 +31,7 @@ def new_github(request):
if gform.is_valid():
try:
api_key = gform.cleaned_data.get("api_key")
g = Github(api_key)
user = g.get_user()
logger.debug("Using user " + user.login)
validate_github_credentials(api_key)

new_j = gform.save(commit=False)
new_j.api_key = api_key
Expand Down
53 changes: 7 additions & 46 deletions dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4084,47 +4084,13 @@ class BannerConf(models.Model):
banner_message = models.CharField(max_length=500, help_text=_("This message will be displayed on the login page. It can contain basic html tags, for example <a href='https://www.fred.com' style='color: #337ab7;' target='_blank'>https://example.com</a>"), default="")


class GITHUB_Conf(models.Model):
configuration_name = models.CharField(max_length=2000, help_text=_("Enter a name to give to this configuration"), default="")
api_key = models.CharField(max_length=2000, help_text=_("Enter your Github API Key"), default="")

def __str__(self):
return self.configuration_name


class GITHUB_Issue(models.Model):
issue_id = models.CharField(max_length=200)
issue_url = models.URLField(max_length=2000, verbose_name=_("GitHub issue URL"))
finding = models.OneToOneField(Finding, null=True, blank=True, on_delete=models.CASCADE)

def __str__(self):
return str(self.issue_id) + "| GitHub Issue URL: " + str(self.issue_url)


class GITHUB_Clone(models.Model):
github_id = models.CharField(max_length=200)
github_clone_id = models.CharField(max_length=200)


class GITHUB_Details_Cache(models.Model):
github_id = models.CharField(max_length=200)
github_key = models.CharField(max_length=200)
github_status = models.CharField(max_length=200)
github_resolution = models.CharField(max_length=200)


class GITHUB_PKey(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)

git_project = models.CharField(max_length=200, blank=True, verbose_name=_("Github project"), help_text=_("Specify your project location. (:user/:repo)"))
git_conf = models.ForeignKey(GITHUB_Conf, verbose_name=_("Github Configuration"),
null=True, blank=True, on_delete=models.CASCADE)
git_push_notes = models.BooleanField(default=False, blank=True, help_text=_("Notes added to findings will be automatically added to the corresponding github issue"))

def __str__(self):
return self.product.name + " | " + self.git_project


from dojo.github.models import ( # noqa: E402, F401 -- backward compat
GITHUB_Clone,
GITHUB_Conf,
GITHUB_Details_Cache,
GITHUB_Issue,
GITHUB_PKey,
)
from dojo.jira.models import ( # noqa: E402,F401 backward compat
JIRA_Instance,
JIRA_Instance_Admin,
Expand Down Expand Up @@ -4776,11 +4742,6 @@ def __str__(self):
admin.site.register(Notes)
admin.site.register(Note_Type)
admin.site.register(Alerts)
admin.site.register(GITHUB_Conf)
admin.site.register(GITHUB_Issue)
admin.site.register(GITHUB_Clone)
admin.site.register(GITHUB_Details_Cache)
admin.site.register(GITHUB_PKey)
admin.site.register(Tool_Configuration, Tool_Configuration_Admin)
admin.site.register(Notification_Webhooks)
admin.site.register(Tool_Product_Settings)
Expand Down
1 change: 1 addition & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [root("dojo/github/templates")],
"APP_DIRS": True,
"OPTIONS": {
"debug": env("DD_DEBUG"),
Expand Down
2 changes: 1 addition & 1 deletion dojo/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
from dojo.engagement.urls import urlpatterns as eng_urls
from dojo.finding.urls import urlpatterns as finding_urls
from dojo.finding_group.urls import urlpatterns as finding_group_urls
from dojo.github_issue_link.urls import urlpatterns as github_urls
from dojo.github.ui.urls import urlpatterns as github_urls
from dojo.group.urls import urlpatterns as group_urls
from dojo.home.urls import urlpatterns as home_urls
from dojo.jira.urls import urlpatterns as jira_urls
Expand Down
2 changes: 1 addition & 1 deletion dojo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from dojo.authorization.roles_permissions import Permissions
from dojo.celery import app
from dojo.finding.queries import get_authorized_findings
from dojo.github import (
from dojo.github.services import (
add_external_issue_github,
close_external_issue_github,
reopen_external_issue_github,
Expand Down
Loading