Adding JSON output for baseline results

This commit adds baseline functionality to the JSON formatter.
Issues will be listed as normal, however if multiple candidates
exist for an issue they'll be listed in 'candidates' with a value
of the list of prospective candidates.

Change-Id: Iaf5bcad52678f768375182175cde8d3efb17b6a3
This commit is contained in:
Travis McPeak 2016-02-10 15:26:15 -08:00
parent a7f5a67066
commit 49780b38af
4 changed files with 30 additions and 4 deletions

View File

@ -128,7 +128,7 @@ Usage::
-b BASELINE, --baseline BASELINE
Path to a baseline report, in JSON format. Note:
baseline reports must be output in one of the
following formats: ['html', 'screen', 'txt']
following formats: ['html', 'json', 'screen', 'txt']
--ini INI_PATH Path to a .bandit file which supplies command line
arguments to Bandit.
--version show program's version number and exit

View File

@ -41,7 +41,7 @@ default_output_format = 'terminal'
logger = logging.getLogger(__name__)
repo = None
report_basename = 'bandit_baseline_result'
valid_baseline_formats = ['txt', 'html']
valid_baseline_formats = ['txt', 'html', 'json']
def main():

View File

@ -101,11 +101,13 @@ from operator import itemgetter
import six
from bandit.core import constants
from bandit.core.test_properties import accepts_baseline
from bandit.core import utils
logger = logging.getLogger(__name__)
@accepts_baseline
def report(manager, filename, sev_level, conf_level, lines=-1):
'''''Prints issues in JSON format
@ -144,7 +146,18 @@ def report(manager, filename, sev_level, conf_level, lines=-1):
results = manager.get_issue_list(sev_level=sev_level,
conf_level=conf_level)
collector = [r.as_dict() for r in results]
baseline = not isinstance(results, list)
if baseline:
collector = []
for r in results:
d = r.as_dict()
if len(results[r]) > 1:
d['candidates'] = [c.as_dict() for c in results[r]]
collector.append(d)
else:
collector = [r.as_dict() for r in results]
if manager.agg_type == 'vuln':
machine_output['results'] = sorted(collector,

View File

@ -12,10 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from collections import OrderedDict
import json
import os
import tempfile
import mock
import testtools
import bandit
@ -41,6 +43,12 @@ class JsonFormatterTests(testtools.TestCase):
self.check_name = 'hardcoded_bind_all_interfaces'
self.issue = issue.Issue(bandit.MEDIUM, bandit.MEDIUM,
'Possible binding to all interfaces.')
self.candidates = [issue.Issue(bandit.LOW, bandit.LOW, 'Candidate A',
lineno=1),
issue.Issue(bandit.HIGH, bandit.HIGH, 'Candiate B',
lineno=2)]
self.manager.out_file = self.tmp_fname
self.issue.fname = self.context['filename']
@ -60,11 +68,15 @@ class JsonFormatterTests(testtools.TestCase):
criteria, rank
)] = 0
def test_report(self):
@mock.patch('bandit.core.manager.BanditManager.get_issue_list')
def test_report(self, get_issue_list):
self.manager.files_list = ['binding.py']
self.manager.scores = [{'SEVERITY': [0] * len(constants.RANKING),
'CONFIDENCE': [0] * len(constants.RANKING)}]
get_issue_list.return_value = OrderedDict([(self.issue,
self.candidates)])
b_json.report(self.manager, self.tmp_fname, self.issue.severity,
self.issue.confidence)
@ -85,3 +97,4 @@ class JsonFormatterTests(testtools.TestCase):
self.assertEqual('binding.py', data['stats'][0]['filename'])
self.assertEqual({'CONFIDENCE': 0, 'SEVERITY': 0},
data['stats'][0]['score'])
self.assertIn('candidates', data['results'][0])