in src/plugins/scanners/jira.py [0:0]
def scan(KibbleBit, source):
jira = re.match(r"(https?://.+)/browse/([A-Z0-9]+)", source['sourceURL'])
if jira:
# JIRA NEEDS credentials to do a proper scan!
creds = None
if source['creds'] and 'username' in source['creds'] and source['creds']['username'] and len(source['creds']['username']) > 0:
creds = "%s:%s" % (source['creds']['username'], source['creds']['password'])
if not creds:
KibbleBit.pprint("JIRA at %s requires authentication, but none was found! Bailing." % source['sourceURL'])
source['steps']['issues'] = {
'time': time.time(),
'status': 'JIRA endpoint requires auth, but none was provided!',
'running': False,
'good': False
}
KibbleBit.updateSource(source)
return
source['steps']['issues'] = {
'time': time.time(),
'status': 'Parsing JIRA changes...',
'running': True,
'good': True
}
KibbleBit.updateSource(source)
badOnes = 0
jsa = []
jsp = []
pendingTickets = []
KibbleBit.pprint("Parsing JIRA activity at %s" % source['sourceURL'])
source['steps']['issues'] = {
'time': time.time(),
'status': 'Downloading changeset',
'running': True,
'good': True
}
KibbleBit.updateSource(source)
# Get base URL, list and domain to parse
u = jira.group(1)
instance = jira.group(2)
lastTicket = 0
latestURL = "%s/rest/api/2/search?jql=project=%s+order+by+createdDate+DESC&fields=id,key&maxResults=1" % (u, instance)
js = None
try:
js = plugins.utils.jsonapi.get(latestURL, auth = creds)
except requests.exceptions.ConnectionError as err:
KibbleBit.pprint("Connection error, skipping this ticket for now!")
source['steps']['issues'] = {
'time': time.time(),
'status': 'Connection error occurred while scanning',
'running': False,
'good': False
}
KibbleBit.updateSource(source)
return
if 'issues' in js and len(js['issues']) == 1:
key = js['issues'][0]['key']
m = re.search(r"-(\d+)$", key)
if m:
lastTicket = int(m.group(1))
openTickets = []
startAt = 0
badTries = 0
while True and badTries < 10:
openURL = "%s/rest/api/2/search?jql=project=%s+and+status=open+order+by+createdDate+ASC&fields=id,key&maxResults=100&startAt=%u" % (u, instance, startAt)
#print(openURL)
try:
ojs = plugins.utils.jsonapi.get(openURL, auth = creds)
if not 'issues' in ojs or len(ojs['issues']) == 0:
break
for item in ojs['issues']:
openTickets.append(item['key'])
KibbleBit.pprint("Found %u open tickets" % len(openTickets))
startAt += 100
except:
KibbleBit.pprint("JIRA borked, retrying")
badTries += 1
KibbleBit.pprint("Found %u open tickets" % len(openTickets))
badOnes = 0
for i in reversed(range(1,lastTicket+1)):
key = "%s-%u" % (instance, i)
pendingTickets.append([key, u, source])
threads = []
block = threading.Lock()
KibbleBit.pprint("Scanning tickets using 4 sub-threads")
for i in range(0,4):
t = jiraThread(block, KibbleBit, source, creds, pendingTickets, openTickets)
threads.append(t)
t.start()
for t in threads:
t.join()
KibbleBit.pprint("Done scanning %s" % source['sourceURL'])
source['steps']['issues'] = {
'time': time.time(),
'status': 'Issue tracker (JIRA) successfully scanned at ' + time.strftime("%Y/%m/%d %H:%M:%S", time.gmtime(time.time())),
'running': False,
'good': True
}
KibbleBit.updateSource(source)