Python jira.JIRA Examples

The following are 30 code examples of jira.JIRA(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module jira , or try the search function .
Example #1
Source File: test_add_issue_with_attachment.py    From zabbix-jira with MIT License 6 votes vote down vote up
def create_issue(to, tittle, body):
    jira_server = {'server': config.jira_server}
    jira = JIRA(options=jira_server, basic_auth=(config.jira_user, config.jira_pass))
    issue_params = {
            'project': {'key': 'HTE'},
            'summary': tittle,
            'description': body,
            'issuetype': {'name': 'Error'},
            'assignee': {'name': to},
    }
    return jira.create_issue(fields=issue_params).key 
Example #2
Source File: jira.py    From pyconjpbot with MIT License 6 votes vote down vote up
def jira_listener(message):
    """
    JIRAのissue idっぽいものを取得したら、そのissueの情報を返す
    """
    # botメッセージの場合は無視する
    if message.body.get('subtype', '') == 'bot_message':
        return

    text = message.body['text'].upper()
    # JIRAのissue idっぽい文字列を取得
    for issue_id in re.findall(r'[A-Z]{3,5}-[\d]+', text):
        # issue_id から issue 情報の attachments を取得
        attachments = create_attachments(issue_id)
        if attachments:
            # issue 情報を送信する
            botwebapi(message, attachments) 
Example #3
Source File: jira.py    From pyconjpbot with MIT License 6 votes vote down vote up
def _build_jql(args, jql_base=''):
    """
    引数から JIRA を検索するための JQL を生成する
    """
    jql = jql_base
    jql += 'project = {}'.format(args.project)
    if args.component:
        component = COMPONENT.get(args.component, args.component)
        jql += ' AND component = {}'.format(component)
    if args.label:
        jql += ' AND labels = {}'.format(args.label)
    if args.keywords:
        target = 'text'
        if args.summary:
            # 要約を検索対象にする
            target = 'summary'
        jql += ' AND {} ~ "{}"'.format(target, ' '.join(args.keywords))

    return jql 
Example #4
Source File: jira.py    From pyconjpbot with MIT License 6 votes vote down vote up
def jira_search(message, keywords):
    """
    JIRAをキーワード検索した結果を返す(オープン状態のみ)
    """

    # 引数を処理する
    try:
        args, argv = parser.parse_known_args(keywords.split())
    except SystemExit:
        botsend(message, '引数の形式が正しくありません')
        _drive_help(message, 'search', '検索')
        return

    # 引数から query を生成
    jql = _build_jql(args, 'status in (Open, "In Progress", Reopened) AND ')

    title = '「{}」の検索結果(オープンのみ)'.format(keywords)
    _send_jira_search_responce(message, jql, title) 
Example #5
Source File: jira.py    From pyconjpbot with MIT License 6 votes vote down vote up
def _send_jira_search_responce(message, query, title):
    """
    JIRAをqueryで検索した結果を返すメソッド
    """
    pretext = title
    pretext += '(<{}/issues/?jql={}|JIRAで見る>)'.format(CLEAN_JIRA_URL, quote(query))
    text = ''

    try:
        issues = jira.search_issues(query)
    except JIRAError as err:
        # なんらかのエラーが発生
        botsend(message, 'JIRAError: `{}`'.format(err.text))
        return

    if issues:
        for issue in issues:
            summary = issue.fields.summary
            key = issue.key
            url = issue.permalink()
            status = issue.fields.status.name
            text += '- <{}|{}> {}({})\n'.format(url, key, summary, status)
    else:
        text += '該当するJIRA issueは見つかりませんでした'

    attachments = [{
        'fallback': title,
        'pretext': pretext,
        'text': text,
    }]
    botwebapi(message, attachments) 
Example #6
Source File: connection.py    From insightconnect-plugins with MIT License 6 votes vote down vote up
def connect(self, params={}):
        self.url = params.get(Input.URL)
        self.username = params.get(Input.USER)
        self.password = params.get(Input.API_KEY).get("secretKey")

        if ".atlassian.net" in self.url or ".jira.com" in self.url:
            self.is_cloud = True

        test_passed = self.test()
        if test_passed:
            client = JIRA(
                options={"server": self.url},
                basic_auth=(
                    self.username,
                    self.password
                )
            )

            self.client = client
            self.rest_client = JiraApi(self.client, self.is_cloud, self.logger) 
Example #7
Source File: app.py    From jira-agile-metrics with MIT License 6 votes vote down vote up
def get_jira_client(connection):
    """Create a JIRA client with the given connection options
    """

    url = connection['domain']
    username = connection['username']
    password = connection['password']
    jira_client_options = connection['jira_client_options']
    jira_server_version_check = connection['jira_server_version_check']

    jira_options = {'server': url}
    jira_options.update(jira_client_options)

    try:
        return JIRA(jira_options, basic_auth=(username, password), get_server_info=jira_server_version_check)
    except Exception as e:
        if e.status_code == 401:
            raise ConfigError("JIRA authentication failed. Check URL and credentials, and ensure the account is not locked.") from None
        else:
            raise 
Example #8
Source File: jira_api.py    From VulnWhisperer with Apache License 2.0 6 votes vote down vote up
def __init__(self, hostname=None, username=None, password=None, path="", debug=False, clean_obsolete=True, max_time_window=12, decommission_time_window=3):
        self.logger = logging.getLogger('JiraAPI')
        if debug:
            self.logger.setLevel(logging.DEBUG)

        if "https://" not in hostname:
            hostname = "https://{}".format(hostname)
        self.username = username
        self.password = password
        self.jira = JIRA(options={'server': hostname}, basic_auth=(self.username, self.password))
        self.logger.info("Created vjira service for {}".format(hostname))
        self.all_tickets = []
        self.excluded_tickets = []
        self.JIRA_REOPEN_ISSUE = "Reopen Issue"
        self.JIRA_CLOSE_ISSUE = "Close Issue"
        self.JIRA_RESOLUTION_OBSOLETE = "Obsolete"
        self.JIRA_RESOLUTION_FIXED = "Fixed"
        self.template_path = 'vulnwhisp/reporting/resources/ticket.tpl'
        self.max_ips_ticket = 30
        self.attachment_filename = "vulnerable_assets.txt"
        self.max_time_tracking = max_time_window #in months
        if path:
            self.download_tickets(path)
        else:
            self.logger.warn("No local path specified, skipping Jira ticket download.")
        self.max_decommission_time = decommission_time_window #in months
        # [HIGIENE] close tickets older than 12 months as obsolete (max_time_window defined)
        if clean_obsolete:
            self.close_obsolete_tickets()
        # deletes the tag "server_decommission" from those tickets closed <=3 months ago
        self.decommission_cleanup()
        
        self.jira_still_vulnerable_comment = '''This ticket has been reopened due to the vulnerability not having been fixed (if multiple assets are affected, all need to be fixed; if the server is down, lastest known vulnerability might be the one reported).
        - In the case of the team accepting the risk and wanting to close the ticket, please add the label "*risk_accepted*" to the ticket before closing it.
        - If server has been decommissioned, please add the label "*server_decommission*" to the ticket before closing it.
        - If when checking the vulnerability it looks like a false positive, _+please elaborate in a comment+_ and add the label "*false_positive*" before closing it; we will review it and report it to the vendor.
        
        If you have further doubts, please contact the Security Team.''' 
Example #9
Source File: jira_notifier.py    From monasca-notification with Apache License 2.0 5 votes vote down vote up
def send_notification(self, notification):
        """Creates or Updates an issue in Jira
        """

        jira_fields = self._build_jira_message(notification)

        parsed_url = urllib.parse.urlsplit(notification.address)
        query_params = urllib.parse.parse_qs(parsed_url.query)
        # URL without query params
        url = urllib.parse.urljoin(
            notification.address,
            urllib.parse.urlparse(
                notification.address).path)

        jira_fields["project"] = query_params["project"][0]
        if query_params.get("component"):
            jira_fields["component"] = query_params["component"][0]

        auth = (
            CONF.jira_notifier.user,
            CONF.jira_notifier.password
        )
        proxy = CONF.jira_notifier.proxy
        proxy_dict = None
        if proxy is not None:
            proxy_dict = {"https": proxy}

        try:
            jira_obj = jira.JIRA(url, basic_auth=auth, proxies=proxy_dict)

            self.jira_workflow(jira_fields, jira_obj, notification)
        except Exception:
            self._log.exception("Error creating issue in Jira at URL {}".format(url))
            return False

        return True 
Example #10
Source File: jira_bulk_changes.py    From SnowAlert with Apache License 2.0 5 votes vote down vote up
def connect_jira():
    print('Connecting to Jira...')
    username = input('Jira username: ')
    pwd = getpass.getpass('Jira password: ')
    try:
        jira_api = JIRA(
            f'https://{JIRA_ACCOUNT}.atlassian.net', basic_auth=(username, pwd)
        )
    except Exception as e:
        print('Error connecting to Jira!\n', e)

    return jira_api 
Example #11
Source File: jira.py    From SnowAlert with Apache License 2.0 5 votes vote down vote up
def escape_jira_strings(v):
    """in JIRA ticket body, "{" and "[" are special symbols that need to be escaped"""
    if type(v) is str:
        return v.replace(r"{", r"\{").replace(r"[", r"\[")
    if type(v) is list:
        return [escape_jira_strings(x) for x in v]
    return escape_jira_strings(str(v)) 
Example #12
Source File: jira.py    From SnowAlert with Apache License 2.0 5 votes vote down vote up
def create_jira_ticket(alert, assignee=None, custom_field=None, project=PROJECT, issue_type=ISSUE_TYPE):
    if not user:
        return

    try:
        alert['EVENT_DATA'] = yaml.dump(
            alert['EVENT_DATA'], indent=4, default_flow_style=False
        )
    except Exception as e:
        log.error("Error while creating ticket", e)

    body = jira_ticket_body(alert, project)

    log.info(f'Creating new JIRA ticket for "{alert["TITLE"]}" in project {project}')

    issue_params = {
        'project': project,
        'issuetype': {'name': issue_type},
        'summary': alert['TITLE'],
        'description': body,
    }

    env_fields = os.environ.get('SA_JIRA_CUSTOM_FIELDS')
    if env_fields or custom_field:
        custom_fields = [f.split('=') for f in env_fields.split(';')]
        for field_id, field_value in custom_fields:
            issue_params[f'customfield_{field_id}'] = {'value': field_value}

        if custom_field:
            issue_params[f'customfield_{custom_field["id"]}'] = {
                'value': custom_field['value']
            }

    new_issue = jira.create_issue(**issue_params)

    if assignee:
        jira.assign_issue(new_issue, assignee)

    return new_issue 
Example #13
Source File: baseClient.py    From reapsaw with Apache License 2.0 5 votes vote down vote up
def connect(self):
        """Connect to Jira. Return None on error """
        try:
            jira = JIRA(environ['JIRA_HOST'], basic_auth=(environ['JIRA_USR'], environ['JIRA_PWD']),
                        options={'verify': False})
            return jira
        except Exception as e:
            logging.error("Failed to connect to JIRA: %s" % e)
            return None 
Example #14
Source File: base.py    From stackstorm-jira with Apache License 2.0 5 votes vote down vote up
def _get_client(self):
        config = self.config

        options = {'server': config['url'], 'verify': config['verify']}

        auth_method = config['auth_method']

        if auth_method == 'oauth':
            rsa_cert_file = config['rsa_cert_file']
            rsa_key_content = self._get_file_content(file_path=rsa_cert_file)

            oauth_creds = {
                'access_token': config['oauth_token'],
                'access_token_secret': config['oauth_secret'],
                'consumer_key': config['consumer_key'],
                'key_cert': rsa_key_content
            }

            client = JIRA(options=options, oauth=oauth_creds)

        elif auth_method == 'basic':
            basic_creds = (config['username'], config['password'])
            client = JIRA(options=options, basic_auth=basic_creds,
                          validate=config.get('validate', False))

        else:
            msg = ('You must set auth_method to either "oauth"',
                   'or "basic" your jira.yaml config file.')
            raise Exception(msg)

        return client 
Example #15
Source File: jira.py    From cc-utils with Apache License 2.0 5 votes vote down vote up
def _from_cfg(
    jira_cfg:model.jira.JiraConfig
) -> jira.JIRA:
    credentials = jira_cfg.credentials()
    return jira.JIRA(
        server=jira_cfg.base_url(),
        basic_auth=credentials.as_tuple(),
    ) 
Example #16
Source File: app.py    From pelorus with Apache License 2.0 5 votes vote down vote up
def collect(self):
        print("Starting Collection")
        options = {
            'server': self.server
        }
        # Connect to Jira
        jira = JIRA(options, basic_auth=(self.user, self.apikey))
        # TODO FIXME This may need to be modified to suit needs and have a time period.
        query_string = "project=" + self.project + " and type=bug and priority=highest"
        # Query Jira and loop results if any are returned.
        critical_issues = jira.search_issues(query_string)
        if len(critical_issues) > 0:
            creation_metric = GaugeMetricFamily('failure_creation_timestamp',
                                                'Failure Creation Timestamp',
                                                labels=['project', 'issue_number'])
            failure_metric = GaugeMetricFamily('failure_resolution_timestamp',
                                               'Failure Resolution Timestamp',
                                               labels=['project', 'issue_number'])
            metrics = self.generate_metrics(self.project, critical_issues)
            for m in metrics:
                if not m.is_resolution:
                    creation_metric.add_metric(m.labels, m.get_value())
                    yield(creation_metric)
                else:
                    failure_metric.add_metric(m.labels, m.get_value())
                    yield(failure_metric) 
Example #17
Source File: close_issue.py    From zabbix-jira with MIT License 5 votes vote down vote up
def close_issue(issue, status):
    jira_server = {'server': config.jira_server}
    jira = JIRA(options=jira_server, basic_auth=(config.jira_user, config.jira_pass))
    jira.transition_issue(issue, status) 
Example #18
Source File: jira_notifier.py    From monasca-notification with Apache License 2.0 5 votes vote down vote up
def jira_workflow(self, jira_fields, jira_obj, notification):
        """How does Jira plugin work?
           1) Check whether the issue with same description exists?
           2) If issue exists, and if it is closed state, open it
           3) if the issue doesn't exist, then create the issue
           4) Add current alarm details in comments
        """

        issue_dict = {'project': {'key': jira_fields["project"]},
                      'summary': jira_fields["summary"],
                      'description': jira_fields["description"],
                      'issuetype': {'name': 'Bug'}, }

        # If the JIRA workflow is created with mandatory components
        if jira_fields.get("component"):
            issue_dict["components"] = [{"name": jira_fields.get("component")}]

        search_term = self._search_query.format(issue_dict["project"]["key"],
                                                CONF.jira_notifier.user,
                                                notification.alarm_id)
        issue_list = jira_obj.search_issues(search_term)
        if not issue_list:
            self._log.debug("Creating an issue with the data {}".format(issue_dict))
            issue = jira_obj.create_issue(fields=issue_dict)
        else:
            issue = issue_list[0]
            self._log.debug("Found an existing issue {} for this notification".format(issue))
            current_state = issue.fields.status.name
            if current_state.lower() in ["resolved", "closed"]:
                # Open the issue
                transitions = jira_obj.transitions(issue)
                allowed_transistions = [(t['id'], t['name'])
                                        for t in transitions if "reopen" in t['name'].lower()]
                if allowed_transistions:
                    # Reopen the issue
                    jira_obj.transition_issue(issue, allowed_transistions[0][0])

        jira_comment_message = jira_fields.get("comments")
        if jira_comment_message:
            jira_obj.add_comment(issue, jira_comment_message) 
Example #19
Source File: types.py    From Kiwi with GNU General Public License v2.0 5 votes vote down vote up
def _rpc_connection(self):
        if hasattr(settings, 'JIRA_OPTIONS'):
            options = settings.JIRA_OPTIONS
        else:
            options = None

        return jira.JIRA(
            self.bug_system.base_url,
            basic_auth=(self.bug_system.api_username, self.bug_system.api_password),
            options=options,
        ) 
Example #20
Source File: cli.py    From jira-agile-metrics with MIT License 5 votes vote down vote up
def configure_argument_parser():
    """Configure an ArgumentParser that manages command line options.
    """

    parser = argparse.ArgumentParser(description='Extract Agile metrics data from JIRA and produce data and charts.')

    # Basic options
    parser.add_argument('config', metavar='config.yml', nargs='?', help='Configuration file')
    parser.add_argument('-v', dest='verbose', action='store_true', help='Verbose output')
    parser.add_argument('-vv', dest='very_verbose', action='store_true', help='Even more verbose output')
    parser.add_argument('-n', metavar='N', dest='max_results', type=int, help='Only fetch N most recently updated issues')
    
    parser.add_argument('--server', metavar='127.0.0.1:8080', help='Run as a web server instead of a command line tool, on the given host and/or port. The remaining options do not apply.')

    # Output directory
    parser.add_argument('--output-directory', '-o', metavar='metrics', help="Write output files to this directory, rather than the current working directory.")

    # Connection options
    parser.add_argument('--domain', metavar='https://my.jira.com', help='JIRA domain name')
    parser.add_argument('--username', metavar='user', help='JIRA user name')
    parser.add_argument('--password', metavar='password', help='JIRA password')
    parser.add_argument('--http-proxy', metavar='https://proxy.local', help='URL to HTTP Proxy')
    parser.add_argument('--https-proxy', metavar='https://proxy.local', help='URL to HTTPS Proxy')
    parser.add_argument('--jira-server-version-check', type=bool, metavar='True', help='If true it will fetch JIRA server version info first to determine if some API calls are available')
    
    return parser 
Example #21
Source File: cli.py    From jira-agile-metrics with MIT License 5 votes vote down vote up
def run_command_line(parser, args):
    if not args.config:
        parser.print_usage()
        return
    
    logging.basicConfig(
        format='[%(asctime)s %(levelname)s] %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        level=(
            logging.DEBUG if args.very_verbose else
            logging.INFO if args.verbose else
            logging.WARNING
        )
    )

    # Configuration and settings (command line arguments override config file options)

    logger.debug("Parsing options from %s", args.config)
    with open(args.config) as config:
        options = config_to_options(config.read(), cwd=os.path.dirname(os.path.abspath(args.config)))

    # Allow command line arguments to override options
    override_options(options['connection'], args)
    override_options(options['settings'], args)

    # Set charting context, which determines how charts are rendered
    set_chart_context("paper")

    # Set output directory if required
    if args.output_directory:
        logger.info("Changing working directory to %s" % args.output_directory)
        os.chdir(args.output_directory)

    # Query JIRA and run calculators

    jira = get_jira_client(options['connection'])

    logger.info("Running calculators")
    query_manager = QueryManager(jira, options['settings'])
    run_calculators(CALCULATORS, query_manager, options['settings']) 
Example #22
Source File: cli.py    From jira-agile-metrics with MIT License 5 votes vote down vote up
def get_jira_client(connection):
    url = connection['domain']
    username = connection['username']
    password = connection['password']
    http_proxy = connection['http_proxy']
    https_proxy = connection['https_proxy']
    jira_server_version_check = connection['jira_server_version_check']

    jira_client_options = connection['jira_client_options']

    logger.info("Connecting to %s", url)

    if not username:
        username = input("Username: ")

    if not password:
        password = getpass.getpass("Password: ")

    options = {'server': url}
    proxies = None

    if http_proxy or https_proxy:
        proxies = {}
        if http_proxy:
            proxies['http'] = http_proxy
        if https_proxy:
            proxies['https'] = https_proxy

    options.update(jira_client_options)

    return JIRA(options, basic_auth=(username, password), proxies=proxies, get_server_info=jira_server_version_check) 
Example #23
Source File: test_add_issue_with_attachment.py    From zabbix-jira with MIT License 5 votes vote down vote up
def add_attachment(issue, attachment):
    jira_server = {'server': config.jira_server}
    jira = JIRA(options=jira_server, basic_auth=(config.jira_user, config.jira_pass))
    jira.add_attachment(issue=issue, attachment=attachment) 
Example #24
Source File: issue_tracker_manager.py    From clusterfuzz with Apache License 2.0 5 votes vote down vote up
def _create_client(self):
    """Return a client object for querying the issue tracker."""
    config = db_config.get()
    credentials = json.loads(config.jira_credentials)
    jira_url = config.jira_url
    jira_client = jira.JIRA(
        jira_url, auth=(credentials['username'], credentials['password']))
    return jira_client 
Example #25
Source File: cli.py    From jira-metrics-extract with MIT License 5 votes vote down vote up
def get_jira_client(connection):
    url = connection['domain']
    token = connection['token']
    try:
        verify = connection['verify']
    except KeyError: #Not found in yaml configuration file
        verify = True # Default should be to verify the certificates to Jira server

    if token:
        username, password = base64.b64decode(token).decode('utf-8').split(':')
    else:
        username = connection['username']
        password = connection['password']

    print("Connecting to ", url)

    if username is None:
        # Fix Python 2.x. raw_input replaced by input in Python 3.x 
        try:
            username = raw_input("Enter Username: ")
        except NameError:
            username = input("Enter username: ")
        except:
            username = getpass.getuser() #Get OS username as as fallback 
            print('No username provided, using username: ' + username)

    if password is None:
        password = getpass.getpass("Enter Password: ")

    if (len(username + password) > 1):
        jiraconnection = JIRA(options={'server': url,'verify': verify}, basic_auth=(username, password))
    else:
        jiraconnection = JIRA(options={'server': url,'verify': verify})
    return jiraconnection 
Example #26
Source File: query.py    From jira-metrics-extract with MIT License 5 votes vote down vote up
def resolve_fields(self):
        fields = self.jira.fields()

        for name, field in self.settings['fields'].items():
            try:
                self.fields[name] = next((f['id'] for f in fields if f['name'].lower() == field.lower()))
            except StopIteration:
                raise Exception("JIRA field with name `%s` does not exist (did you try to use the field id instead?)" % field) 
Example #27
Source File: jira_api.py    From VulnWhisperer with Apache License 2.0 5 votes vote down vote up
def create_ticket(self, title, desc, project="IS", components=[], tags=[], attachment_contents = []):
        labels = ['vulnerability_management']
        for tag in tags:
            labels.append(str(tag))

        self.logger.info("Creating ticket for project {} title: {}".format(project, title[:20]))
        self.logger.debug("project {} has a component requirement: {}".format(project, components))
        project_obj = self.jira.project(project)
        components_ticket = []
        for component in components:
            exists = False
            for c in project_obj.components:
                if component == c.name:
                    self.logger.debug("resolved component name {} to id {}".format(c.name, c.id))
                    components_ticket.append({ "id": c.id })
                    exists=True
            if not exists:
                self.logger.error("Error creating Ticket: component {} not found".format(component))
                return 0
        
        try:
            new_issue = self.jira.create_issue(project=project,
                                               summary=title,
                                               description=desc,
                                               issuetype={'name': 'Bug'},
                                               labels=labels,
                                               components=components_ticket)
            
            self.logger.info("Ticket {} created successfully".format(new_issue))
            
            if attachment_contents:
                self.add_content_as_attachment(new_issue, attachment_contents)
        
        except Exception as e:
            self.logger.error("Failed to create ticket on Jira Project '{}'. Error: {}".format(project, e))
            new_issue = False
        
        return new_issue
    
    #Basic JIRA Metrics 
Example #28
Source File: jira_api.py    From VulnWhisperer with Apache License 2.0 5 votes vote down vote up
def exclude_accepted_assets(self, vuln):
        # we want to check JIRA tickets with risk_accepted/server_decommission or false_positive labels sharing the same source
        # will exclude tickets older than 12 months, old tickets will get closed for higiene and recreated if still vulnerable
        labels = [vuln['source'], vuln['scan_name'], 'vulnerability_management', 'vulnerability'] 
        
        if not self.excluded_tickets:
            jql = "{} AND labels in (risk_accepted,server_decommission, false_positive) AND NOT labels=advisory AND created >=startOfMonth(-{})".format(" AND ".join(["labels={}".format(label) for label in labels]), self.max_time_tracking)
            self.excluded_tickets = self.jira.search_issues(jql, maxResults=0)

        title = vuln['title']
        #WARNING: function IGNORES DUPLICATES, after finding a "duplicate" will just return it exists
        #it wont iterate over the rest of tickets looking for other possible duplicates/similar issues
        self.logger.info("Comparing vulnerability to risk_accepted tickets")
        assets_to_exclude = []
        tickets_excluded_assets = []
        for index in range(len(self.excluded_tickets)):
            checking_ticketid, checking_title, checking_assets = self.ticket_get_unique_fields(self.excluded_tickets[index])
            if title.encode('ascii') == checking_title.encode('ascii'):
                if checking_assets:
                    #checking_assets is a list, we add to our full list for later delete all assets
                    assets_to_exclude+=checking_assets
                    tickets_excluded_assets.append(checking_ticketid)
       
        if assets_to_exclude:
            assets_to_remove = []
            self.logger.warn("Vulnerable Assets seen on an already existing risk_accepted Jira ticket: {}".format(', '.join(tickets_excluded_assets)))
            self.logger.debug("Original assets: {}".format(vuln['ips']))
            #assets in vulnerability have the structure "ip - hostname - port", so we need to match by partial 
            for exclusion in assets_to_exclude:
                # for efficiency, we walk the backwards the array of ips from the scanners, as we will be popping out the matches 
                # and we don't want it to affect the rest of the processing (otherwise, it would miss the asset right after the removed one)
                for index in range(len(vuln['ips']))[::-1]:
                    if exclusion == vuln['ips'][index].split(" - ")[0]:
                        self.logger.debug("Deleting asset {} from vulnerability {}, seen in risk_accepted.".format(vuln['ips'][index], title))
                        vuln['ips'].pop(index)
            self.logger.debug("Modified assets: {}".format(vuln['ips']))

        return vuln 
Example #29
Source File: jira_api.py    From VulnWhisperer with Apache License 2.0 5 votes vote down vote up
def check_vuln_already_exists(self, vuln):
        '''
        This function compares a vulnerability with a collection of tickets.
        Returns [exists (bool), is equal (bool), ticketid (str), assets (array)]
        '''
        # we need to return if the vulnerability has already been reported and the ID of the ticket for further processing
        #function returns array [duplicated(bool), update(bool), ticketid, ticket_assets]
        title = vuln['title']
        labels = [vuln['source'], vuln['scan_name'], 'vulnerability_management', 'vulnerability'] 
        #list(set()) to remove duplicates
        assets = list(set(re.findall(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", ",".join(vuln['ips']))))
        
        if not self.all_tickets:
            self.logger.info("Retrieving all JIRA tickets with the following tags {}".format(labels))
            # we want to check all JIRA tickets, to include tickets moved to other queues
            # will exclude tickets older than 12 months, old tickets will get closed for higiene and recreated if still vulnerable
            jql = "{} AND NOT labels=advisory AND created >=startOfMonth(-{})".format(" AND ".join(["labels={}".format(label) for label in labels]), self.max_time_tracking)
            
            self.all_tickets = self.jira.search_issues(jql, maxResults=0)
        
        #WARNING: function IGNORES DUPLICATES, after finding a "duplicate" will just return it exists
        #it wont iterate over the rest of tickets looking for other possible duplicates/similar issues
        self.logger.info("Comparing Vulnerabilities to created tickets")
        for index in range(len(self.all_tickets)):
            checking_ticketid, checking_title, checking_assets = self.ticket_get_unique_fields(self.all_tickets[index])
            # added "not risk_accepted", as if it is risk_accepted, we will create a new ticket excluding the accepted assets
            if title.encode('ascii') == checking_title.encode('ascii') and not self.is_risk_accepted(self.jira.issue(checking_ticketid)): 
                difference = list(set(assets).symmetric_difference(checking_assets))
                #to check intersection - set(assets) & set(checking_assets)
                if difference: 
                    self.logger.info("Asset mismatch, ticket to update. Ticket ID: {}".format(checking_ticketid))
                    return False, True, checking_ticketid, checking_assets #this will automatically validate
                else:
                    self.logger.info("Confirmed duplicated. TickedID: {}".format(checking_ticketid))
                    return True, False, checking_ticketid, [] #this will automatically validate
        return False, False, "", [] 
Example #30
Source File: jirabix.py    From zabbix-jira with MIT License 5 votes vote down vote up
def jira_login():
    jira_server = {'server': config.jira_server}
    return JIRA(options=jira_server, basic_auth=(config.jira_user, config.jira_pass))