def update_epic(engagement): logger.info('trying to update jira EPIC for %d:%s', engagement.id, engagement.name) if not is_jira_configured_and_enabled(engagement): return False logger.debug('config found') jira_project = get_jira_project(engagement) jira_instance = get_jira_instance(engagement) if jira_project.enable_engagement_epic_mapping: try: jira = get_jira_connection(jira_instance) j_issue = get_jira_issue(engagement) issue = jira.issue(j_issue.jira_id) issue.update(summary=engagement.name, description=engagement.name) return True except JIRAError as e: logger.exception(e) log_jira_generic_alert('Jira Engagement/Epic Update Error', str(e)) return False else: messages.add_message( get_current_request(), messages.ERROR, 'Push to JIRA for Epic skipped because enable_engagement_epic_mapping is not checked for this engagement', extra_tags='alert-danger') return False
def get_jira_meta(jira, jira_project): meta = jira.createmeta( projectKeys=jira_project.project_key, issuetypeNames=jira_project.jira_instance.default_issue_type, expand="projects.issuetypes.fields") # logger.debug("get_jira_meta: %s", json.dumps(meta, indent=4)) # this is None safe # meta['projects'][0]['issuetypes'][0]['fields']: meta_data_error = False if len(meta['projects']) == 0: # non-existent project, or no permissions # [09/Nov/2020 21:04:22] DEBUG [dojo.jira_link.helper:595] get_jira_meta: { # "expand": "projects", # "projects": [] # } meta_data_error = True message = 'unable to retrieve metadata from JIRA %s for project %s. Invalid project key or no permissions to this project?' % ( jira_project.jira_instance, jira_project.project_key) elif len(meta['projects'][0]['issuetypes']) == 0: # default issue type doesn't exist in project # [09/Nov/2020 21:09:03] DEBUG [dojo.jira_link.helper:595] get_jira_meta: { # "expand": "projects", # "projects": [ # { # "expand": "issuetypes", # "self": "https://jira-uat.com/rest/api/2/project/1212", # "id": "1212", # "key": "ISO", # "name": "ISO ISMS", # "avatarUrls": { # "48x48": "https://jira-uat.com/secure/projectavatar?pid=14431&avatarId=17200", # "24x24": "https://jira-uat.com/secure/projectavatar?size=small&pid=14431&avatarId=17200", # "16x16": "https://jira-uat.com/secure/projectavatar?size=xsmall&pid=14431&avatarId=17200", # "32x32": "https://jira-uat.com/secure/projectavatar?size=medium&pid=14431&avatarId=17200" # }, # "issuetypes": [] # } # ] # } meta_data_error = True message = 'unable to retrieve metadata from JIRA %s for issuetype %s in project %s. Invalid default issue type configured in Defect Dojo?' % ( jira_project.jira_instance, jira_project.jira_instance.default_issue_type, jira_project.project_key) if meta_data_error: logger.warn(message) logger.warn("get_jira_meta: %s", json.dumps(meta, indent=4)) # this is None safe messages.add_message(get_current_request(), messages.ERROR, message, extra_tags='alert-danger') raise JIRAError(text=message) else: return meta
def add_epic(engagement): logger.info('trying to create a new jira EPIC for %d:%s', engagement.id, engagement.name) if not is_jira_configured_and_enabled(engagement): return False logger.debug('config found') jira_project = get_jira_project(engagement) jira_instance = get_jira_instance(engagement) if jira_project.enable_engagement_epic_mapping: issue_dict = { 'project': { 'key': jira_project.project_key }, 'summary': engagement.name, 'description': engagement.name, 'issuetype': { 'name': 'Epic' }, 'customfield_' + str(jira_instance.epic_name_id): engagement.name, } try: jira = get_jira_connection(jira_instance) logger.debug('add_epic: %s', issue_dict) new_issue = jira.create_issue(fields=issue_dict) j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue.key, engagement=engagement, jira_project=jira_project) j_issue.save() return True except JIRAError as e: # should we try to parse the errors as JIRA is very strange in how it responds. # for example a non existent project_key leads to "project key is required" which sounds like something is missing # but it's just a non-existent project (or maybe a project for which the account has no create permission?) # # {"errorMessages":[],"errors":{"project":"project is required"}} logger.exception(e) error = str(e) message = "" if "customfield" in error: message = "The 'Epic name id' in your DefectDojo Jira Configuration does not appear to be correct. Please visit, " + jira_instance.url + \ "/rest/api/2/field and search for Epic Name. Copy the number out of cf[number] and place in your DefectDojo settings for Jira and try again. For example, if your results are cf[100001] then copy 100001 and place it in 'Epic name id'. (Your Epic Id will be different.) \n\n" log_jira_generic_alert('Jira Engagement/Epic Creation Error', message + error) return False else: messages.add_message( get_current_request(), messages.ERROR, 'Push to JIRA for Epic skipped because enable_engagement_epic_mapping is not checked for this engagement', extra_tags='alert-danger') return False
def get_jira_connection_raw(jira_server, jira_username, jira_password): try: jira = JIRA(server=jira_server, basic_auth=(jira_username, jira_password), options={"verify": settings.JIRA_SSL_VERIFY}, max_retries=0) logger.debug('logged in to JIRA ' '%s' ' successfully', jira_server) return jira except JIRAError as e: logger.exception(e) if e.status_code in [401, 403]: log_jira_generic_alert('JIRA Authentication Error', e) else: log_jira_generic_alert('Unknown JIRA Connection Error', e) messages.add_message( get_current_request(), messages.ERROR, 'Unable to authenticate. Please check the URL, username, password, captcha challenge, Network connection. Details in alert on top right. ' + e.text, extra_tags='alert-danger') raise e except requests.exceptions.RequestException as re: logger.exception(re) log_jira_generic_alert('Unknown JIRA Connection Error', re) messages.add_message( get_current_request(), messages.ERROR, 'Unable to authenticate. Please check the URL, username, password, IP whitelist, Network connection. Details in alert on top right.', extra_tags='alert-danger') raise re
def close_epic(eng, push_to_jira): engagement = eng if not is_jira_enabled(): return False if not is_jira_configured_and_enabled(engagement): return False jira_project = get_jira_project(engagement) jira_instance = get_jira_instance(engagement) if jira_project.enable_engagement_epic_mapping: if push_to_jira: try: jissue = get_jira_issue(eng) if jissue is None: logger.warn("JIRA close epic failed: no issue found") return False req_url = jira_instance.url + '/rest/api/latest/issue/' + \ jissue.jira_id + '/transitions' json_data = { 'transition': { 'id': jira_instance.close_status_key } } r = requests.post(url=req_url, auth=HTTPBasicAuth(jira_instance.username, jira_instance.password), json=json_data) if r.status_code != 204: logger.warn("JIRA close epic failed with error: {}".format( r.text)) return False return True except JIRAError as e: logger.exception(e) log_jira_generic_alert('Jira Engagement/Epic Close Error', str(e)) return False else: messages.add_message( get_current_request(), messages.ERROR, 'Push to JIRA for Epic skipped because enable_engagement_epic_mapping is not checked for this engagement', extra_tags='alert-danger') return False
def add_error_message_to_response(message): if get_current_request(): messages.add_message(get_current_request(), messages.ERROR, message, extra_tags='alert-danger')